Java设计模式
2013年09月16日


单例模式的使用场景:


1、缓存资源,控制资源的并发读、写。(资源即类的属性)
例如:有一把锁,需要两把钥匙才能打开。在更换钥匙期间,是不允许开锁的。
而且,两把钥匙必须更换完才允许开锁,即,只更换完一把时,是不允许开锁的。

假设一个线程修改完了一把钥匙,正准备修改第二把钥匙,而此时另外一个线程又试图开锁。
有两种做法:
1)此时不允许开锁,必须等第二把钥匙更改完成后才允许。
2)允许开锁,仍然用未更改的旧钥匙。
读的时候,为提高效率,最好能避免使用synchronized同步。


设计模式:
Proxy
Adapter
Decorator
Wrapper
Delegate

区别:

Proxy:某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动。
Proxy就象一道墙,其他程序只能和Proxy交互操作。

用法1: 授权、检查机制。
比如,通过ForumProxy代理,控制用户对论坛的访问权限。代码如下:
public class ForumProxy implements Forum {
 private ForumPermissions permissions;
 private Forum forum;
 public ForumProxy(Forum forum, ForumPermissions permissions){
    this.forum = forum;
    this.permissions = permissions;
 }
 public void setName(String name) {
     //只有是系统或论坛管理者才可以修改名称
     if (permissions.isSystemOrForumAdmin()) {
       forum.setName(name);
     }
 }
}

只能通过ForumProxy来创建Forum,并且要求传入ForumPermissions。在setName的时候,会首先检查权限。

动态代理就是这个系列的一种高级实现方式。

用法2:延迟初始化。先要获得某种资源,但是不急着去使用它。
例如,如果直接用
ABC obj= new ABC(); // 或者 ABC obj = getABC();
obj.doXXX();
假设获得obj的过程很漫长,而且不会立即用到,那么就建立一个ABCProxy对象,然后再调用代理对象的doXXX()方法:
void doXXX(){
 ABC obj= new ABC(); // 或者 ABC obj = getABC();
 obj.doXXX();
}

Decorator模式:
不改变原来定义的类,但是又想给他增加功能。而且又不想继承它。
那就用Decorator模式,例如BufferedReader:
 FileReader fr = new FileReader(filename);
 BufferedReader br = new BufferedReader(fr);
将原来的对象作为参数传到Decorator中,注意
Decorator和原来的对象,都implements了同一个接口,比如Reader。
调用Decorator时,可以在原对象的方法前后,加上Decorator自定义的方法。

Decorator模式和Proxy模式的区别在于,Decorator着重于“增加功能”,而Proxy着重于“改造”。
通常来说,Proxy的使用频率比Decorator要高。


Adapter模式:将两个类组合在一起使用,建立一种统一的使用方法。
例如,假设我们有两种打桩方式:方形桩、圆形桩。现在有一个应用,需要既打方形桩,又打圆形桩。
实现方式如下:
public class PegAdapter extends SquarePeg {
    private RoundPeg roundPeg;
    public PegAdapter(RoundPeg peg) {
        this.roundPeg=peg;    
    }
     // 打桩-同时打两个
    public void insert(String str) { 
        super.insert(str); 
        roundPeg.insertIntoHole(str);
    }
}

加入:需要打桩,但是打什么类型的桩是动态确定的。

实现方式如下:
public class PegAdapter implements IRoundPeg, ISquarePeg{
    private RoundPeg roundPeg;
    private SquarePeg squarePeg;
    // 构造方法 - RoundPeg
    public PegAdapter(RoundPeg peg){
        this.roundPeg=peg;
    }
    // 构造方法 - SquarePeg
    public PegAdapter(SquarePeg peg){
        this.squarePeg=peg;
    }
    // 打桩-选择一个打桩
    public void insert(String str){ 
        if(roundPeg!=null) 
            roundPeg.insertIntoHole(str); 
        else 
            squarePeg.insertIntoHole(str);}
    }
}

Strategy(策略模式)

跟Adapter模式类似,比Adapter模式狭隘。用于动态确定调用的对象。
例如:
我们要建立一个算法解决类,用来提供客户端可以自由选择算法。
public class RepTempRuleSolve {
     // 实际的算法对象
    private RepTempRule strategy;
     // 指定算法
    public RepTempRuleSolve(RepTempRule rule){
        this.strategy=rule;
    }
     // 切换算法
    public void changeAlgorithm(RepTempRule newAlgorithm) {
        strategy = newAlgorithm;
    }
    public String doService(Site site,String oldString) {
        return strategy.replace(site,oldString);
    }
}