您的位置:首页 > 其它

设计模式总结

2017-04-13 10:12 260 查看
 设计模式总结

http://blog.csdn.net/joyney/category/434480.aspx
http://www.jdon.com/designpatterns/index.htm
http://www.cnblogs.com/kid-li/category/44668.html
 
       Singleton 单件模式解决的问题是:实体对象个数问题(这个现在还不太容易混)
      FactoryMethod 工厂方法模式解决的问题是:某个对象的创建工作
       AbstractFactory 抽象工厂模式解决的问题是:“一系列互相依赖的对象”的创建工作.
工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).
这两个模式区别在于需要创建对象的复杂程度上 。
 
       Builder 生成器模式解决的问题是:“一些复杂对象”的创建工作, 子对象变化较频繁,对算法相对稳定
 
1、 原型模式:prototype模式:
         注意:原型模式是通过拷贝自身来创建新的对象,这一点和其他创建型模式不相同。
  java.lang.Object 本身即定义有 clone() 方法 ,因此所有的对象基本上 皆具自我复制之能力,不过真正要让对象支持复制,则对象必须实作 java.lang.Cloneable 这个接口
 
2、建造者模式:builder模式
Builder模式是一步一步创建一个复杂的对象,因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮 方向盘 发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder模式就是为了将部件和组装过程分开.
 
其中的类或对象之间的关系为:
      Builder:抽象建造者
     为创建一个Product对象的各个部件指定抽象接口。
      ConcreteBuilder:具体建造者
       1.实现Builder接口,构造和装配产品的各个部件.
       2.定义并明确它所创建的表示.
       3.提供一个返回这个产品的接口。
      Director:指挥者
       构建一个使用Builder接口的对象。
           调用具体建造者角色以创建产品对象;
      Product:产品角色
        1.被构建的复杂对象,具体建造者创建该产品的内部表示并表示定义它的装配过程。
        2.包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
 
为什么需要Director:
 在这个模式中,Director类好像是一个多余的类,在应用中的作用好像并不大。其实它的作用是明显的。第一,它隔离了客户及生产过程。第二,它负责控制产品的生成过程。比如你是客户,你要买汽车,你选好车型、颜色、内外装饰等,交给Director,Director告诉你去某车间取车就可以。这样其作用大家都能体会出来了吧。
 
Builder模式与AbstractFactory模式的区别:
建造者模式(Builder)与抽象工厂模式很相象,但是,Builder返回完整的一个产品,而AbstractFactory返回一系列有关系的产品;在抽象工厂模式中,客户采用AbstractFactory生成自己要用的对象,而在建造者模式中,客户指导Builder类如何生成对象,或者如何合成一些类来构成建造类,侧重于一步步构造一个复杂对象,然后将结果返回。
 
ConcreteBuilder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
House house = builder.getHouse();

 
参考:http://blog.csdn.net/joyney/archive/2009/03/18/4000741.aspx
http://www.blogjava.net/amigoxie/archive/2007/03/18/104610.html
http://www.jdon.com/designpatterns/builder.htm
 
3、Singleton模式
主要作用是保证一个类Class只有一个实例存在。
几种形式:
public class Singleton {

  private Singleton(){}

  //在自己内部定义自己一个实例,是不是很奇怪?
  //注意这是private 只供内部调用

  private static Singleton instance = new Singleton();

  //这里提供了一个供外部访问本class的静态方法,可以直接访问  
  public static Singleton getInstance() {
    return instance;   
   }
}

 第二种形式:
public class Singleton {

  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  if (instance==null)
    instance=new Singleton();
  return instance;   }

}

第三种:
 
public class Singleton {

private static class Holder {
private static final Singleton instance = new Singleton();
}

private Singleton() {
}

public static Singleton getInstance() {
return Holder.instance;
}
}

 
上面第二中形式是lazy initialization,也就是说第一次调用时初始Singleton,以后就不用再生成了。
注意到lazy initialization形式中的synchronized,这个synchronized很重要,如果没有synchronized,那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论,有兴趣者进一步研究。
一般认为第一种形式要更加安全些。
 
 
//DCL
public class LazySingleton {
private static volatile LazySingleton instance;

public static LazySingleton getInstantce() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}

 当然还有一种方式是使用重入锁ReentrantLock.
 
 Java:单例模式的七种写法
http://icewubin.iteye.com/blog/256869
 
4、外观模式:Facade模式
为子系统中的一组接口提供一个一致的界面.
从某种程度上也达到了一种“解耦”的效果——内部子系统的任何变化不会影响到 Facade 接口的变化。
 
5、代理模式:Proxy模式
代理模式的作用是:为对象提供一种代理以控制对这个对象的访问。 在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式一般涉及到三个角色:

抽象角色 :声明真实对象和代理对象的共同接口;

代理角色 :代理对象角色 内部含有对真实对象的引用,从而可以操作真实对象 ,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

真实角色 :代理角色所代表的真实对象,是我们最终要引用的对象。
 
6、适配器模式:Adapter模式
1.概念:
把一个类的接口变换成客户端所希望的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
(就是将两个类的方法组合起来,使其可以在一个类中使用!)
2.两种形式
a.类的适配器模式 b.对象的适配器模式
http://www.iteye.com/topic/339198
http://www.iteye.com/topic/74417
http://www.iteye.com/topic/54212
 
8、装饰模式:Decorator模式
动态给一个对象添加一些额外的职责 .使用Decorator模式比生成子类方式达到功能的扩充显得更为灵活.
主要是解决:“过度地使用了继承来扩展对象的功能 ”
装饰模式和继承都是对功能的扩展,而装饰模式使用的是组合,使用过多的继承会增加系统的复杂性和偶合性。
Work squarePeg = new SquarePeg();
Work decorator = new Decorator(squarePeg);
//注意此处squarePeg为具体的实例对象
decorator.insert();

 
上面调用类似我们读取文件时的调用:
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);

 
 
实际上Java 的I/O API就是使用Decorator模式实现的,I/O变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐.
参考:http://www.iteye.com/topic/121149
http://www.jdon.com/designpatterns/decorator.htm
 
适配器模式:将一个类的接口,转换成客户期望的另外一个接口。适配器让原本接口不兼容的类可以很好的合作。 

装饰者模式:动态的将责任附加到对象上(因为利用组合而不是继承来实现,而组合是可以在运行时进行随机组合的)。若要扩展功能,装饰者提供了比继承更富有弹性的替代方案(同样地,通过组合可以很好的避免类暴涨,也规避了继承中的子类必须无条件继承父类所有属性的弊端)。

特点:

1. 装饰者和被装饰者拥有相同的超类型(可能是抽象类也可能是接口)

2. 可以用多个装饰类来包装一个对象,装饰类可以包装装饰类或被装饰对象

3. 因为装饰者和被装饰者拥有相同的抽象类型,因此在任何需要原始对象(被包装)的场合,都可以用装饰过的对象来替代它。

4. 装饰者可以在被装饰者的行为之前或之后,加上自己的附加行为,以达到特殊目的

5. 因为对象可以在任何的时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象

 

PS:java.io库是最好的例子

小结:装饰者模式——动态地将责任附加到对象上。想要扩展功能,装饰者提供了有别于继承的另外一种选择。是一个很好的符合了开闭原则的设计模式。

  

总结:适配器模式主要是为了接口的转换,而装饰者模式关注的是通过组合来动态的为被装饰者注入新的功能或行为(即所谓的责任)。

适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增强新的行为和责任;而外观将一群对象包装起来以简化其接口

 
 
7、组合模式:composite模式
将对象组合成树形结构 以表示部分和整体的层次结构.
组合模式使得用户对单个对象和组合对象的适用具有一致性.
 
    组合模式是将对象之间的关系以数据结构中的2 叉树表现出来,使得客户端将单纯的元素与复杂元素同等看待,这样的话使得用户在操作不同的子类元素时可以和根节点元素一样操作,在透明模式下即根元素和叶元素公用同一个接口达到共同的结果。
组合模式就是解决部分与整体的关系的一种模式。
 
意图
将对象组合成树形结构以表示“整体 - 部分”的层次结构。 Composite 使得用户对单个对象和组合对象的使用具有一致性
动机
客户代码过多的依赖于对象容器复杂的内部实现结构,对象容器内部实现结构(非抽象接口)的变化将引起客户代码的频繁变化代码的代码维护和扩展的困难,我们需要将客户代码与复杂的对象容器结构解偶。
适用性
l          想表示对象的部分 - 整体层次结构
l          希望用户忽略组合对象与单个对象的不同 ,用户将统一地使用组合结构中的所有对象。
结构
 


 
参与者
l          抽象构件( Component )角色                           ( IComposite )               
l          树叶构件( Leaf )角色                 (Employees )
l          树枝构件                       (Boss)
Composite 模式的优点
1.          客户代码不依赖复杂对象本身的结构变化
2.          用户不需要特别关心复杂对象的具体结构只要等同于根对象操作
http://uule.iteye.com/blog/868224
 
 
9、桥接模式: Bridge模式
将抽象部分与实现部分分离 ,使它们都可以独立的变化。
 
任何事物对象都有抽象和行为之分,例如人,人是一种抽象,人分男人和女人等;人有行为,行为也有各种具体表现,所以,“人”与“人的行为”两个概念也反映了抽象和行为之分。
在面向对象设计的基本概念中,对象这个概念实际是由属性和行为两个部分组成的,属性我们可以认为是一种静止的,是一种抽象,一般情况下,行为是包含在一个对象中,但是,在有的情况下,我们需要将这些行为也进行归类,形成一个总的行为接口,这就是桥模式的用处。
 
http://www.cnblogs.com/houleixx/archive/2008/02/23/1078877.html
http://www.jdon.com/designpatterns/bridge.htm
http://flysnail.iteye.com/blog/183668
 
10、模板模式:Template模式
一. 模式概述
      摸板方法(Template Method)模式是一种非常简单而又经常使用的设计模式.先创建一个父类,把其中的一个或多个方法留给子类去实现 ,这实际上就是在使用摸板模式.所谓的摸板模式可以这样来理解:"在一个类中定义一个算法,但将此算法的某些细节留到子类中去实现.换句话说,基类是一个抽象类,那么你就是在使用一种简单形式的摸板模式."
二. 模式意图
      将一个类的基本部分抽取出来放到一个基类中,这样它就不必重复出现在几个派生类里. 
三. 模式UML图
                           


四. 模式结构与参与者
   

 抽象摸板角色:
        1. 定义了一个或多个抽象操作,以便让子类实现.
        2. 定义并实现了一个摸板方法.
   

 具体摸板角色:
        1. 实现父类所定义的一个或多个抽象方法.
        2. 每一个抽象摸板角色都可以有任意多个具体摸板角色与之对应.
        3. 每一个具体摸板角色都可以给出这些抽象方法的不同实现.
 
11、备忘录模式:memento模式
1. 定义
        在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
2. 使用的原因
         想要恢复对象某时的原有状态
public class Originator {

  public int number;

  public File file = null;

  public Originator(){}

  // 创建一个Memento
  public Memento getMemento(){
    return new Memento(this);
  }

  // 恢复到原始值
  public void setMemento(Memento m){
     number = m.number;
     file = m.file;
  }

}

 
private class Memento implements java.io.Serializable{

  public int number;

  public File file = null;

  public Memento( Originator o){

    number = o.number;
    file = o.file;

  }

}

 
可见 Memento中保存了Originator中的number和file的值. Originator中number和file值改变的话,通过调用setMemento()方法可以恢复.
Memento模式的缺点是耗费大,如果内部状态很多,再保存一份,无意要浪费大量内存.
http://www.jdon.com/designpatterns/memento.htm
http://blog.csdn.net/joyney/archive/2009/04/07/4054594.aspx
http://peirenlei.iteye.com/blog/364399
 
12、
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: