为软件系统的子系统、组件或者组件之间的关系提供一个精炼之后的解决方案
它描述了在特定环境下,用于解决通用软件设计问题的组件以及这些组件相互通信时的可重现结构 -creational pattern
抽象了实例化过程,帮助一个系立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象 -structural pattern
涉及到如何组合类和对象以获得更大的结构。结构型类模式使用继承机制来组合接口和实现。结构型对象模式描述了如何对一些对象进行组合,从而实现新功能的一些方法。 -behavioral pattern
涉及到算法和对象间职责的分配。不仅描述对象或类的模式还描述他们之间的通信模式。行为类模式使用继承机制在类间分配行为。行为对象模式使用对象复合而不是继承。
(1)Template method(模板方法):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。这里的算法的结构,可以理解为你根据需求设计出来的业务流程。特定的步骤就是指那些可能在内容上
存在变数的环节。
1) AbstractClass(抽象类):定义了一到多个的抽象方法,以供具体的子类来实现它们;而且还要实现一个模板方法,来定义一个算法的骨架。该模板方法不仅调用前面的抽象方法,也可以调用其他的操作,只要能完成自身的使命。
2) ConcreteClass(具体类):实现父类中的抽象方法以完成算法中与特定子类相关的步骤。
(2)Façade(外观模式):外观模式(Facade pattern)为子系统提供了一个更高层次、更简单的接口,从而降低了子系统的复杂度和依赖。这使得子系统更易于使用和管理。
外观是一个能为子系统和客户提供简单接口的类。当正确的应用外观,客户不再直接和子系统中的类交互,而是与外观交互。外观承担与子系统中类交互的责任。实际上,外观是子系统与客户的接口,这样外观模式降低了子系统和客户的耦合度(Figure2).
从图中我们可以看到:外观对象隔离了客户和子系统对象,从而降低了耦合度。当子系统中的类进行改变时,客户端不会像以前一样受到影响。
(3)Proxy(代理模式):它建议创建那些占用大量内存或处理复杂的对象时,把创建这类对象推迟到使用它的时候。
这时,需要设计一个与真实对象具有相同接口的单独对象(指虚
拟代理)。不同的客户对象在创建和使用真实对象地方用相应的虚拟对象来代替。虚拟对象把真实对象的引用作为它的属性变量。代理对象不会自动创建真实对象,当客户需要真实对象的服务时,调用虚拟代理对象上的方法,并且检测真实对象是否被创建。如果真实对象已经创建,代理把调用转发给真实对象,如果真实对象没有被创建: 1) 代理对象创建真实对象
2) 代理对象把这个对象分配给引用变量。 3) 代理把调用转发给真实对象
public abstract class IDEOperation { //功能类的抽象父类
private Compiler cmp; private Runtime rtime; public IDEOperation() { cmp = new Compiler();
rtime = new Runtime(); }
public void compile(String javaFile) { cmp.compile(javaFile); }
public void run(String classFile) { rtime.run (classFile);
} //该方法会等到子类去实现 public abstract void generateDocs(String javaFile); }
public class RealProcessor extends IDEOperation { //功能类实现父类
JavaDoc jdoc;
public RealProcessor() { super();
jdoc = new JavaDoc(); }
public void generateDocs(String javaFile) { //实现父类中的方法 jdoc.generateDocs(javaFile); } }
public class ProxyProcessor extends IDEOperation { //代理功能类,继承同一个父类(相同接口)
private RealProcessor realProcessor; //真实功能类的一个对象引用。 if (realProcessor == null) {
realProcessor = new RealProcessor(); }
realProcessor.generateDocs(javaFile); } }
public class Client {
//客户程序
public static void main(String[] args) {
IDEOperation IDE = new ProxyProcessor(); //客户使用代理类 IDE.compile(\"test.java\"); IDE.run(\"test.class\");
IDE.generateDocs(\"test.java\"); //客户对象像调用真实处理对象一样调用
ProxyProcessor上的方法,并不需要关心(知道)RealProcessor对象是否存在。
public void generateDocs(String javaFile) { //用户调用代理类的此方法
客户对象像调用真实处理对象一样调用ProxyProcessor上的方法,并不需要关心(知道)RealProcessor对象是否存在。
} }
(4)Decorator(装饰器模式)
使用场景:动态的给一个对象添加额外的职责
1、装饰器模式主要装饰供外部调用的接口方法,如果一个接口方法只是提供给内部调用,则不能使用该模式。
2、装饰器模式主要装饰可能要改变的接口方法,如果类中的某种行为在将来可能发生变化,而你又懒得去改变原来的类,那么就可以考虑使用装饰器模式了。
//接口或者抽象基类
public interface IDecorate {
public void sayHello(); }
//被装饰对象,实现了前面提到的接口或者抽象基类的实现类。
public class DecorateImpl implements IDecorate {
public void sayHello() {
System.out.print(\"Hello\"); } }
//装饰对象,就是去装饰被装饰对象的对象。和被装饰对象继承同一个父类。
public class Decorate implements IDecorate {
//声明一个被装饰的对象 private IDecorate decorate;
//被装饰对象从装饰器的构造函数中传进来(必须这样做) public Decorate(IDecorate decorate) {
this.decorate = decorate; }
//在基类装饰器中只调用被装饰对象的方法 public void sayHello() {
decorate.sayHello(); } }
//继承装饰对象类的子类,也就是具体的装饰器类了
public class SimpleDecorate extends Decorate {
public SimpleDecorate(IDecorate decorate) {
super(decorate); }
//开装饰了哦。。。 public void sayHello() {
//在原来的方法中加入了sayChina方法。 sayChina();
super.sayHello();
//在原来的方法中加入了sayWorld方法。 sayWorld(); }
public void sayChina() {
System.out.print(\"China, \"); }
public void sayWorld()
{
System.out.print(\" World!\\n\"); } }
//来,测试一下
public void TestDecorate() {
//使用装饰器
public static void useDecorate(IDecorate decorate) {
IDecorate simpleDecorate = new SimpleDecorate(decorate);
//要调用装饰了的方法
//输出 China, Hello World! simpleDecorate.sayHello(); }
(5)Bridge(桥模式):桥梁模式的用意是将问题的抽象和实现分离开来
实现,通过用聚合代替继承来解决子类爆炸性增长的问题。
比如我们有一个画图程序 有2个图形(Circle,Rectangle )和2种画图方法(Drawing1, Drawing2) 图形可能会使用Drawing1来画图 也可能使用
Drawing2来画图。在这个画图程序中有两个可变因素 一个是图形的种类 有可能会增加新的图形 另一个是画图方法 可能会有Drawing3出现
当系统有两个可变因素时 我就应该考虑到桥梁模式,至少它应该在你的脑子里闪过
在面向对象设计中有两条重要原则 1.找出变化并封装之
2.优先使用聚合而不是继承
在上例中图形是一个变化 我们可以抽象出一个形状接口 和 一些形状类 1. interface Shape{ 2. void doDraw(); 3. }
4. class Circle implements Shape{} 5. class Rectangle implements Shape{}
画图方法也可以抽象出一个Drawing接口 和 各种画法 1. interface Drawing{ 2. void draw(); 3. }
4. class Drawing1 implements Drawing{} 5. class Drawing2 implements Drawing{}
最后将两个变化联系起来
在问题域中是图形使用画图方法 所有应该在Shape中使用Drawing
我们可以通过在具体的图形类中通过构造函数传入具体的画图方法来实现 如下
1. class Circle implements Shape{
2. private Drawing drawing; //组合要调用的类 3. public Circle(Drawing drawing){ 4. this.drawing = drawing; 5. } 6.
7. public void doDrow(){ 8. drawing.draw(); 9. } 10.} 11.
12.class Client(){
13. public static void main(String[] args){
14. Shape circle = new Circle(new Drawing2()); 15. circle.draw(); 16. } 17.}
(6)Factory method(工厂方法模式):定义一个创建产品对象的工厂接口,将实
际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
抽象工厂(Creator)角色:任何在模式中创建的对象的工厂类必须实现这
个接口。 AbstractFactory
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,
包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。FactoryA,FactoryB„„
抽象产品(Product)角色:工厂方法模式所创建的对象的超类型,也就是产
品对象的共同父类或共同拥有的接口。Plant,Fruit
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义
的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应。PlantA,PlantB,FruitA,FruitB„„
(7)组合模式(Composite Pattern)
定义
组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式(Composite Pattern) 结构图
Component为组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件 abstract class Component {
protected string name;
public Component( string name) {
this .name = name; }
public abstract void Add(component c); // 通常都用Add和Remove方法来提供增
加或移出树叶或树枝的功能
public abstract void Remove(Component c); public abstract void Display( in depth); }
Leaf在组合中表示叶节点对象,叶节点没有子节点
class Leaf extends Component {
public Leaf( string name): base (name) {}
public override void Add(Component c) // 由于叶节点没有再增加分枝和树叶,
所以Add和Remove方法实现
{
Console.WriteLine( \" Cannot add to a leaf \" );
}
public override void Remove(Component c) {
Console.WriteLine( \" Cannot remove to a leaf \" ); }
public override void Display( int depth) {
// 叶节点的具体方法,此处是显示其名称和级别 Console.WriteLine(); } }
Composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加Add和删除Remove class Composite extends Component {
private List < Component > children = new List < Component > (); public Composite( string name): base (name) {}
public override void Add(Component c) {
children.add(c); }
public override void Remove(Component c) {
children.Remove(c); }
public override void Display( int depth) { // 显示枝节点名称,并对其下级进行遍历
Console.WriteLine( new string ( ' - ' ,depth) + name); foreach (Component component in children) {
component.Display(depth + 2 ); }
} }
客户端代码,能通过Component接口操作组合部件的对象 static void Main( string [] args) {
Component root = new Component( \" root \" );
root.Add( new Leaf( \" Leaf A \" )); // 生成树根root,根上长出两叶 root.Add( new Leaf( \" Leaf B \" )); // LeafA与LeafB
Composite comp = new Composite( \" Componsite X \" ); comp.Add( new Leaf( \" Leaf XA \" )); comp.Add( new Leaf( \" Leaf XB \" )); root.Add(comp);
Composite comp2 = new Composite( \" Composite XY \" ); comp2.Add( new Leaf( \" Leaf XYA \" )); comp2.Add( new Leaf( \" Leaf XYB \" )); comp.Add(comp2);
// 根部又长出两页LeafC和LeafD,可惜LeafD没有长牢,被风吹走了 root.Add( new Leaf( \" Leaf c \" ));
Leaf leaf = new Leaf( \" Leaf D \" ); root.Add(leaf); root.Remove(leaf);
root,Display( 1 ); // 显示大树的样子 }
显示结果: - root --- leaf A --- leaf B
--- Composite X ----- Leaf XA ----- Leaf XB
----- Composite XY ------- Composite XYA ------- Composite XYB --- Leaf c
适用场景
当需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象象的不同时,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了
与单个对
组合模式的优点:
组合模式定义了包含基本对象和组合对象的类层次结构。基本对象可以被组合成更复杂的组合 对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的 地方都可以使用组合对象了。 用户不用关心到底是处理一个叶节点还是处理一个组合组件, 也就是用不着为定义组合而写一些选择判断语句了,简单地说就是组合模式让客户可以一致地使用 组合结构和单个对象。
透明方式: 也就是说在Component中声明所有用来管理子对象的方法中,其中包括Add、Remove 等。这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点 和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf 类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的。
安全方式: 也就是在Component接口中不去声明Add和Remove方法,那么子类的Leaf也不需要去实现它,而是在 Composite声明所有用来管理子类对象的方法。不过由于不透明,所以树叶和树枝将不具有相同的接口, 客户端的调用需要做相应的判断,带来了不便 。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- stra.cn 版权所有 赣ICP备2024042791号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务