学习设计模式是一个漫长的过程,需要在编程过程中不断思考不断应用,才能逐渐领悟其本质。在此记录学习设计模式的点滴心得,温故而知新....

设计模式心得:

  • 策略模式:实现算法的封装,动态使用不同的算法接口
  • 观察者模式:Java中可以通过继承java.util.Observable 来方便实现观察者模式,由于Java不能多继承,所以有时需要在继承其它类的基础上自己实现观察者模式。
  • 装饰者模式:动态将责任添加给对象,类似于递归,层层迭代。典型应用为:
    OutputStream out=new DataOutputStream(new BufferOutputStream(new FileOutputStrem));
  • 工厂模式:静态工厂可以定义简单的工厂,不需要实例化。缺点是不能通过继承来改变创建的行为(自己以前对工厂模式停留在这个层面)。工厂方法用来处理对象的创建,并将这种行为封装在子类中。
abstract Product factoryMethod(...type)  
  • 抽象工厂模式
  • 单件模式:形式相对简单,应用领域——线程池、缓存、对话框、偏好设置、注册表以及日志、驱动等对象。管理共享的资源,“延迟实例化”只有在用到的时候才会创建。注意多进程调用的同步问题,比如在创建实例的时候,同时利用双重检查加锁(double-checked locking),同步一次,提高效率。Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值。而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在任何时刻,两个不同的线程总是看到某个成员变量的同一个值。
public class Singleton{
    public volatile static Singleton uniqueInstance;
    public static Singleton getInstance(){
        if(uniqueInstance==null){
               synchronized(Singleton.class){
                    if(uniqueInstance==null)return new Singleton();
               }
        }
    }
}    
  •  命令模式:将请求调用者和请求执行者解耦,请求调用者执行时不需要知道具体细节,请求执行者被封装入特定的命令对象,在excute()中被调用。可以实现宏命令,调用一连串的命令。更多用途,队列请求(228页),日志请求(229页)...
public interface Command{
    public void execute();
}
public AnyCommand implements Command{
    AnyCommand(Receiver receiver){}
    public void execute(){
        receiver.doSomething();
    }
    
}
public Invoker{
    public void setCommand(Command c){}
    public void invoke(){
        c.execute();
    }
}

 

  • 空对象模式:空对象的使用被看做一种设计模式,为了避免每次都检查obj!=null而存在,实现空对象执行内容为空,是个比较实用的实现。
  • 适配器模式:将接口转换成不同的接口。有对象适配器和类适配器(java不支持多重继承的类适配器)。
  • 外观模式(Facade-Pattern):用于简化接口,实现一连串接口的调用。但不封装子系统,可以理解成快捷键、一键安装之类的实现。
  • 迭代器模式 :提供一种方法顺序访问聚合对象中的各个元素,而不暴露其内部的表示。如实现java.util.Iterator或ListIterator等迭代器接口等。Java5中可以使用for(Object obj:collection)完成迭代。
  • 组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。组合包含组件。组件有两种,组合和叶节点元素。通过让组件的接口同时包含一些管理子节点和叶节点的操作,客户就可以将组合和叶节点一视同仁,一个元素究竟是组合还是叶节点对客户透明。
//组合迭代器实现的精彩递归案例
import
java.util.*; public class CompositeIterator implements Iterator{ Stack stack = new Stack(); public CompositeIterator(Iterator iterator){ stack.push(iterator); } public Object next(){ if(hasNext()){ Iterator iterator = (Iterator)stack.peek(); MenuComponet componet =(MenuComponet) iterator.next(); if(componet instanceof Menu){ stack.push(component.createIterator()); } return component; }else{ return null; } public boolean hasNext(){ if(stack.empty()){return false;} else{ Iterator iterator=(Iterator) stack.peek(); if(!iterator.hasNext()){ stack.pop(); return hasNext(); }else{ return true;} } public void remove(){ throw new UnsupportedOperationException(); } }
  •  状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。这个模式将状态封装成为独立的类,并将动作委托到代表当前状态的对象。
  • 代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。常见代理有(1)远程代理在java中可以通过RMI实现,在java5中有新的实现方式。(2)虚拟代理作为创建开销大的对象的代表,如书中实现的获取远程图片的虚拟代理。(3)保护代理如书中实现的利用InvocationHandler实现动态代理保护。其它代理实现Firewall Proxy,Smart Reference Proxy,Caching Proxy,Synchornization Proxy,Complexity Hiding Proxy,Copy-On-Write Proxy。注意和装饰模式的区别,代理模式为了控制对象的访问,装饰模式为了增加行为。

 

设计模式中的原则

 “最小知识”原则——就任何对象而言,在该对象的方法内,我们只应该调用属于以下部分的方法

  1. 该对象本身
  2. 被当做方法的参数而传进来的对象
  3. 此方法所创建的或实例化的任何对象
  4. 对象的任何组建

如果对象是调用其它方法的返回结果,则不要调用该对象的方法,如下:

public void callMethod(){
    Object1 obj1=obj2.getObject1();
    obj1.callMethod();
System.out.print("同样违反了该原则....") }

 虽然该原则会减少维护成本,但是导致复杂度和开发时间的增加,并降低了运行时的性能。

“好莱坞原则”——允许低层组件将自己挂钩到系统上,但是高层组件决定什么时候和怎么样使用这些组件。是创建框架或组件上的技巧,让低层挂钩到高层,高层又不依赖低层。

“依赖倒置原则”——要依赖抽象,不要依赖具体类。教我们尽量避免使用具体类,多使用抽象。

好莱坞原则和依赖倒置原则目标都是解耦,但是依赖倒置原则更加注重如何在设计中避免依赖,好莱坞原则教我们一个技巧,允许低层结构能互相作用,而又防止其他类过于依赖他们。

 


设计模式的思想是高度统一的,只是在不同应用场景中会有不同的区别,所以产生了不同的设计模式,需要分清楚他们的作用和区别。

模板方法:子类决定如何实现算法中的步骤,定义算法大纲。工厂方法是模板方法的一种特殊版本。策略和模板都是封装算法,前者用组合后者用继承实现。

策略:封装可互换的行为,然后使用委托来决定采用哪一个行为。定义算法家族,并让算法可以互换。

工厂方法:由子类决定实例化哪个具体的类。

 

 

posted on 2012-09-27 17:28  Drinking  阅读(169)  评论(0编辑  收藏  举报