斗爷

导航

PatternsInJava文摘

1. Factory

定义:提供创建对象的接口.

为何使用?我们需要将创建实例的责任与使用实例的责任分开

public class Factory{
public static Sample creator(){
....
if (which==1)
return new MySample();
else if (which==2)
return new HisSample();
}
}

如何使用?
工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).

这两个模式没有很明显的区别,区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,我们就可能要将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现

public abstract class Factory{
public abstract Sample creator();
public abstract Sample2 creator();
}
public class SimpleFactory extends Factory{
public Sample creator(){
......
}
public Sample2 creator(){
......
}
}
public class BombFactory extends Factory{
public Sample creator(){
......
}
public Sample2 creator(){
......
}
}

上例中我们只有一类产品接口 Sample , 工厂方法和抽象工厂可以创建多个产品接口的实例,比如Sample2 Sample3
FactoryMethod 往往只是创建单个的实例。Abstract Factory 创建一系列的实例组,这些实例彼此相关。

2. Prototype

定义:
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.

如何使用?
因为Java 中的提供clone()方法来实现对象的克隆(具体了解clone()按这里),所以
Prototype 模式实现一下子变得很简单.

public abstract class AbstractSpoon implements Cloneable
{
String spoonName;
public void setSpoonName(String spoonName) {this.spoonName = spoonName;}
public String getSpoonName() {return this.spoonName;}
public Object clone()
{
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println("AbstractSpoon is not Cloneable");
}
return object;
}
}
public class SaladSpoon extends AbstractSpoon
{
public SaladSpoon()
{
setSpoonName("Salad Spoon");
}
}
public class SoupSpoon extends AbstractSpoon
{
public SoupSpoon()
{
setSpoonName("Soup Spoon");
}
}

AbstractSpoon spoon1 = new SoupSpoon();
AbstractSpoon spoon2 = spoon1.clone();

3. Builder

Builder 模式定义:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.

为何使用?
是为了将构建复杂对象的过程和它的部件解耦.注意: 是解耦过程和部件.

如何使用?

public interface Builder {
//创建部件A 比如创建汽车车轮
void buildPartA();
//创建部件B 比如创建汽车方向盘
void buildPartB();
//创建部件C 比如创建汽车发动机
void buildPartC();
//返回最后组装成品结果 (返回最后装配好的汽车)
//成品的组装过程不在这里进行,而是转移到下面的Director 类中
进行.
//从而实现了解耦过程和部件
Product getResult();
}
public class ConcreteBuilder implements Builder {
Part partA, partB, partC;
public void buildPartA() {
//这里是具体如何构建partA 的代码
};
public void buildPartB() {
//这里是具体如何构建partB 的代码
};
public void buildPartC() {
//这里是具体如何构建partB 的代码
};
public Product getResult() {
//返回最后组装成品结果
};
}
public class Director {
private Builder builder;
public Director( Builder builder ) {
this.builder = builder;
}
// 将部件partA partB partC 最后组成复杂对象
//这里是将车轮 方向盘和发动机组装成汽车的过程
public void construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
}
}

复杂对象:产品Product:
public interface Product { }
复杂对象的部件:
public interface Part { }

我们看看如何调用Builder 模式:
ConcreteBuilder builder = new ConcreteBuilder();
Director director = new Director( builder );
director.construct();
Product product = builder.getResult();

4. Singleton

定义:
Singleton 模式主要作用是保证在Java 应用程序中,一个Class 只有一个实例存在。

如何使用?

public class Singleton {
private static Singleton _instance = new Singleton();
public static Singleton getInstance() {
return _instance;
}
}
调用方法:
Singleton.getInstance()
public class Singleton {
private static Singleton _instance = null;
public static Singleton getInstance() {
if (_instance==null)
_instancenew Singleton()
return _instance;
}
}
调用方法:
Singleton.getInstance()

5. Facade

Facade 的定义: 为子系统中的一组接口提供一个一致的界面.

Facade 一个典型应用就是数据库JDBC 的应用,如下例对数据库的操作:

public class DBCompare {
Connection conn = null;
PreparedStatement prep = null;
ResultSet rset = null;
try {
Class.forName( "<driver>" ).newInstance();
conn = DriverManager.getConnection( "<database>" );
String sql = "SELECT * FROM <table> WHERE <column name> = ?";
prep = conn.prepareStatement( sql );
prep.setString( 1, "<column value>" );
rset = prep.executeQuery();
if( rset.next() ) {
System.out.println( rset.getString( "<column name" ) );
}
} catch( SException e ) {
e.printStackTrace();
} finally {
rset.close();
prep.close();
conn.close();
}
}

上例是Jsp 中最通常的对数据库操作办法.
在应用中,经常需要对数据库操作,每次都写上述一段代码肯定比较麻烦,需要将其中不变的
部分提炼出来,做成一个接口,这就引入了facade 外观对象.如果以后我们更换
Class.forName 中的<driver>也非常方便,比如从Mysql 数据库换到Oracle 数据库,只要更
换facade 接口中的driver 就可以.

6.Proxy

Proxy 是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结
构,Proxy 是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到
目的地之间有一道中间层,意为代理.
设计模式中定义: 为其他对象提供一种代理以控制对这个对象的访问.

为什么要使用Proxy?
1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive 论坛系统中,就使用
Proxy 进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive 中就通过
类似ForumProxy 这样的代理来控制这两种用户对论坛的访问权限.
2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.
举例两个具体情况:
(1)如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包
含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处
理完成,这时需要做个图片Proxy 来代替真正的图片.
(2)如果那个对象在Internet 的某个远端服务器上,直接操作这个对象因为网络速度原因可
能比较慢,那我们可以先用Proxy 来代替那个对象.
总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝
贵的Java 内存. 所以,有些人认为Java 耗费资源内存,我以为这和程序编制思路也有一定的
关系.

public class ForumProxy implements Forum {
private ForumPermissions permissions;
private Forum forum;
this.authorization = authorization;
public ForumProxy(Forum forum, Authorization authorization,
ForumPermissions permissions)
{
this.forum = forum;
this.authorization = authorization;
this.permissions = permissions;
}
.....
public void setName(String name) throws UnauthorizedException,
ForumAlreadyExistsException
{
//只有是系统或论坛管理者才可以修改名称
if (permissions.isSystemOrForumAdmin()) {
forum.setName(name);
}
else {
throw new UnauthorizedException();
}
}

而DbForum 才是接口Forum 的真正实现,以修改论坛名称为例:

public class DbForum implements Forum, Cacheable {
...
public void setName(String name) throws
ForumAlreadyExistsException {
....
this.name = name;
//这里真正将新名称保存到数据库中
saveToDb();
....
}
...
}

7.Adapter

定义:
将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和
Adaptor(适配器)两个身份.

为何使用?
我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,
但是如果我们没有源代码,或者,我们不愿意为了一个应用而修改各自的接口。 怎么办?
使用Adapter,在这两种接口之间创建一个混合接口(混血儿).

如何使用?
实现Adapter 方式,其实"think in Java"的"类再生"一节中已经提到,有两种方式:组合
(composition)和继承(inheritance).
假设我们要打桩,有两种类:方形桩 圆形桩.

public class SquarePeg{
public void insert(String str){
System.out.println("SquarePeg insert():"+str);
}
}
public class RoundPeg{
public void insertIntohole(String msg){
System.out.println("RoundPeg insertIntoHole():"+msg);
}
}
public class PegAdapter extends SquarePeg{
private RoundPeg roundPeg;
public PegAdapter(RoundPeg peg)(this.roundPeg=peg;)
public void insert(String str){ roundPeg.insertIntoHole(str);}
}

8.Composite

Composite 定义:
将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和
组合对象的使用具有一致性.

Composite 比较容易理解,想到Composite 就应该想到树形结构图。组合体内这些对象都有
共同接口,当组合体一个对象的方法被调用执行时,Composite 将遍历(Iterator)整个树形
结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。
所以Composite 模式使用到Iterator 模式,和Chain of Responsibility 模式类似。
Composite 好处:
1.使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自
己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。

public abstract class Equipment
{
private String name;
//网络价格
public abstract double netPrice();
//折扣价格
public abstract double discountPrice();
//增加部件方法
public boolean add(Equipment equipment) { return false; }
//删除部件方法
public boolean remove(Equipment equipment) { return false; }
//注意这里,这里就提供一种用于访问组合体类的部件方法。
public Iterator iter() { return null; }
public Equipment(final String name) { this.name=name; }
}
public class Disk extends Equipment
{
public Disk(String name) { super(name); }
//定义Disk 网络价格为1
public double netPrice() { return 1.; }
//定义了disk 折扣价格是0.5 对折。
public double discountPrice() { return .5; }
}
abstract class CompositeEquipment extends Equipment
{
private int i=0;
//定义一个Vector 用来存放'儿子'
private Lsit equipment=new ArrayList();
public CompositeEquipment(String name) { super(name); }
public boolean add(Equipment equipment) {
this.equipment.add(equipment);
return true;
}
public double netPrice()
{
double netPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())
netPrice+=((Equipment)iter.next()).netPrice();
return netPrice;
}
public double discountPrice()
{
double discountPrice=0.;
Iterator iter=equipment.iterator();
for(iter.hasNext())
设计模式(Patterns in Java) -- http://www.jdon.com
35
discountPrice+=((Equipment)iter.next()).discountPrice();
return discountPrice;
}
//注意这里,这里就提供用于访问自己组合体内的部件方法。
//上面dIsk 之所以没有,是因为Disk 是个单独(Primitive)的元素.
public Iterator iter()
{
return equipment.iterator() ;
{
//重载Iterator 方法
public boolean hasNext() { return i<equipment.size(); }
//重载Iterator 方法
public Object next()
{
if(hasNext())
return equipment.elementAt(i++);
else
throw new NoSuchElementException();
}
}
public class Chassis extends CompositeEquipment
{
public Chassis(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice()
{ return .5+super.discountPrice(); }
}
public class Cabinet extends CompositeEquipment
{
设计模式(Patterns in Java) -- http://www.jdon.com
36
public Cabinet(String name) { super(name); }
public double netPrice() { return 1.+super.netPrice(); }
public double discountPrice()
{ return .5+super.discountPrice(); }
}

至此我们完成了整个Composite 模式的架构。
我们可以看看客户端调用Composote 代码:
Cabinet cabinet=new Cabinet("Tower");
Chassis chassis=new Chassis("PC Chassis");
//将PC Chassis 装到Tower 中 (将盘盒装到箱子里)
cabinet.add(chassis);
//将一个10GB 的硬盘装到 PC Chassis (将硬盘装到盘盒里)
chassis.add(new Disk("10 GB"));
//调用 netPrice()方法;
System.out.println("netPrice="+cabinet.netPrice());
System.out.println("discountPrice="+cabinet.discountPrice());
上面调用的方法netPrice()或discountPrice(),实际上Composite 使用Iterator 遍历了
整个树形结构,寻找同样包含这个方法的对象并实现调用执行.
Composite 是个很巧妙体现智慧的模式,在实际应用中,如果碰到树形结构,我们就可以尝
试是否可以使用这个模式。

9.Decorator

Decorator 定义:
动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator 模式相比用生成
子类方式达到功能的扩充显得更为灵活.

为什么使用Decorator?
我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势
必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓
展功能,这些功能是编译时就确定了,是静态的.
使用Decorator 的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator 提供
了"即插即用"的方法,在运行期间决定何时增加何种功能.

public interface Work
{
public void insert();
}

public class SquarePeg implements Work{
public void insert(){
System.out.println("方形桩插入");
}
}

public class Decorator implements Work{
private Work work;
//额外增加的功能被打包在这个List 中
private ArrayList others = new ArrayList();
//在构造器中使用组合new 方式,引入Work 对象;
public Decorator(Work work)
{
this.work=work;
others.add("挖坑");
others.add("钉木板");
}
public void insert(){
newMethod();
}
//在新方法中,我们在insert 之前增加其他方法,这里次序先后是用
户灵活指定的
public void newMethod()
{
otherMethod();
work.insert();
}
public void otherMethod()
{
ListIterator listIterator = others.listIterator();
while (listIterator.hasNext())
{
System.out.println(((String)(listIterator.next()))
+ " 正在进行");
}
}
}

好了,Decorator 模式出来了,我们看如何调用:
Work squarePeg = new SquarePeg();
Work decorator = new Decorator(squarePeg);
decorator.insert();
Decorator 模式至此完成.
如果你细心,会发现,上面调用类似我们读取文件时的调用:
FileReader fr = new FileReader(filename);
BufferedReader br = new BufferedReader(fr);
实际上Java 的I/O API 就是使用Decorator 实现的,I/O 变种很多,如果都采取继承方法,
将会产生很多子类,显然相当繁琐

10.Bridge

Bridge 定义 :
将抽象和行为划分开来,各自独立,但能动态的结合.

为什么使用?
通常,当一个抽象类或接口有多个具体实现(concrete subclass),这些concrete 之间关系可
能有以下两种:
1. 这多个具体实现之间恰好是并列的,如前面举例,打桩,有两个concrete class:方形桩和
圆形桩;这两个形状上的桩是并列的,没有概念上的重复,那么我们只要使用继承就可以了.
2.实际应用上,常常有可能在这多个concrete class 之间有概念上重叠.那么需要我们把抽
象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个
接口,分别放置抽象和行为.
例如,一杯咖啡为例,有中杯和大杯之分,同时还有加奶 不加奶之分. 如果用单纯的继承,这
四个具体实现(中杯 大杯 加奶 不加奶)之间有概念重叠,因为有中杯加奶,也有中杯不加奶,
如果再在中杯这一层再实现两个继承,很显然混乱,扩展性极差.那我们使用Bridge 模式来
实现它.
如何实现?
以上面提到的咖啡 为例. 我们原来打算只设计一个接口(抽象类),使用Bridge 模式后,我
们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.

public abstract class Coffee
{
CoffeeImp coffeeImp;
public void setCoffeeImp() {
this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
}
public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}
public abstract void pourCoffee();
}
public abstract class CoffeeImp
{
public abstract void pourCoffeeImp();
}
//中杯
public class MediumCoffee extends Coffee
{
public MediumCoffee() {setCoffeeImp();}
public void pourCoffee()
{
CoffeeImp coffeeImp = this.getCoffeeImp();
//我们以重复次数来说明是冲中杯还是大杯 ,重复2 次是中杯
for (int i = 0; i < 2; i++)
{
coffeeImp.pourCoffeeImp();
}
}
}
//大杯
public class SuperSizeCoffee extends Coffee
{
public SuperSizeCoffee() {setCoffeeImp();}
public void pourCoffee()
{
CoffeeImp coffeeImp = this.getCoffeeImp();
//我们以重复次数来说明是冲中杯还是大杯 ,重复5 次是大杯
for (int i = 0; i < 5; i++)
{
coffeeImp.pourCoffeeImp();
}
}
}
//加奶
public class MilkCoffeeImp extends CoffeeImp
{
MilkCoffeeImp() {}
public void pourCoffeeImp()
{
System.out.println("加了美味的牛奶");
}
}
//不加奶
public class FragrantCoffeeImp extends CoffeeImp
{
FragrantCoffeeImp() {}
public void pourCoffeeImp()
{
System.out.println("什么也没加,清香");
}
}
public class CoffeeImpSingleton
{
private static CoffeeImp coffeeImp;
public CoffeeImpSingleton(CoffeeImp coffeeImpIn)
{this.coffeeImp = coffeeImpIn;}
public static CoffeeImp getTheCoffeeImp()
{
return coffeeImp;
}
}

看看中杯加奶 和大杯加奶 是怎么出来的:
//拿出牛奶
CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new
MilkCoffeeImp());
//中杯加奶
MediumCoffee mediumCoffee = new MediumCoffee();
mediumCoffee.pourCoffee();
//大杯加奶
SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();
superSizeCoffee.pourCoffee();
注意: Bridge 模式的执行类如CoffeeImp 和Coffee 是一对一的关系, 正确创建CoffeeImp
是该模式的关键,

11.Flyweight

Flyweight 定义:
避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类).

为什么使用?
面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞
大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗
费内存,那么我们还是要"求同存异",找出这些对象群的共同点,设计一个元类,封装可以被
共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight 中两
个重要概念内部状态intrinsic 和外部状态extrinsic 之分.
说白点,就是先捏一个的原始模型,然后随着不同场合和环境,再产生各具特征的具体模型,
很显然,在这里需要产生不同的新对象,所以Flyweight 模式中常出现Factory 模
式.Flyweight 的内部状态是用来共享的,Flyweight factory 负责维护一个Flyweight
pool(模式池)来存放内部状态的对象.
Flyweight 模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度.应用场合
很多:比如你要从一个数据库中读取一系列字符串,这些字符串中有许多是重复的,那么我们
可以将这些字符串储存在Flyweight 池(pool)中.

public interface Flyweight
{
public void operation( ExtrinsicState state );
}
//用于本模式的抽象数据类型(自行设计)
public interface ExtrinsicState { }
public class ConcreteFlyweight implements Flyweight {
private IntrinsicState state;
public void operation( ExtrinsicState state )
{
//具体操作
}
}
public class UnsharedConcreteFlyweight implements Flyweight {
public void operation( ExtrinsicState state ) { }
}

Flyweight factory 负责维护一个Flyweight 池(存放内部状态),当客户端请求一个共享
Flyweight 时,这个factory 首先搜索池中是否已经有可适用的,如果有,factory 只是简单返
回送出这个对象,否则,创建一个新的对象,加入到池中,再返回送出这个对象.池

public class FlyweightFactory {
//Flyweight pool
private Hashtable flyweights = new Hashtable();
public Flyweight getFlyweight( Object key ) {
Flyweight flyweight = (Flyweight) flyweights.get(key);
if( flyweight == null ) {
//产生新的ConcreteFlyweight
flyweight = new ConcreteFlyweight();
flyweights.put( key, flyweight );
}
return flyweight;
}
}

至此,Flyweight 模式的基本框架已经就绪,我们看看如何调用:
FlyweightFactory factory = new FlyweightFactory();
Flyweight fly1 = factory.getFlyweight( "Fred" );
Flyweight fly2 = factory.getFlyweight( "Wilma" );

12.Template

Template 定义:
定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中.

public abstract class Benchmark
{
/**
* 下面操作是我们希望在子类中完成
*/
public abstract void benchmark();
/**
* 重复执行benchmark 次数
*/
public final long repeat (int count) {
if (count <= 0)
return 0;
else {
long startTime = System.currentTimeMillis();
for (int i = 0; i < count; i++)
benchmark();
long stopTime = System.currentTimeMillis();
return stopTime - startTime;
}
}
}
public class MethodBenchmark extends Benchmark
{
/**
* 真正定义benchmark 内容
*/
public void benchmark() {
for (int i = 0; i < Integer.MAX_VALUE; i++){
System.out.printtln("i="+i);
}
}
}

Benchmark operation = new MethodBenchmark();
long duration = operation.repeat(Integer.parseInt(args[0].trim()));
System.out.println("The operation took " + duration + " milliseconds");

13.Memento

Memento 定义:
memento 是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原
先保存的状态.

public class Originator {
private int number;
private 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{
private int number;
private File file = null;
public Memento( Originator o){
number = o.number;
file = o.file;
}
}

可见 Memento 中保存了Originator 中的number 和file 的值. 通过调用Originator 中
number 和file 值改变的话,通过调用setMemento()方法可以恢复.
Memento 模式的缺点是耗费大,如果内部状态很多,再保存一份,无意要浪费大量内存.

14.Observer

public class product extends Observable{
private String name;
private float price;
public String getName(){ return name;}
public void setName(){
this.name=name;
//设置变化点
setChanged();
notifyObservers(name);
}
public float getPrice(){ return price;}
public void setPrice(){
this.price=price;
//设置变化点
setChanged();
notifyObservers(new Float(price));
}
//以下可以是数据库更新 插入命令.
public void saveToDb(){
.....................
}
//观察者NameObserver 主要用来对产品名称(name)进行观察的
public class NameObserver implements Observer{
private String name=null;
public void update(Observable obj,Object arg){
if (arg instanceof String){
name=(String)arg;
//产品名称改变值在name 中
System.out.println("NameObserver :name changet to "+name);
}
}
}
//观察者PriceObserver 主要用来对产品价格(price)进行观察的
public class PriceObserver implements Observer{
private float price=0;
public void update(Observable obj,Object arg){
if (arg instanceof Float){
price=((Float)arg).floatValue();
System.out.println("PriceObserver :price changet to "+price);
}
}
}

Product product=new Product();
NameObserver nameobs=new NameObserver();
PriceObserver priceobs=new PriceObserver();
//加入观察者
product.addObserver(nameobs);
product.addObserver(priceobs);
product.setName("橘子红了");
product.setPrice(9.22f);

15.Chain of Responsibility

Chain of Responsibility 定义
Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些
类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说,来了一个请
求,A 类先处理,如果没有处理,就传递到B 类处理,如果没有处理,就传递到C 类处理,
就这样象一个链条(chain)一样传递下去。

CoR 的优点:
因为无法预知来自外界的请求是属于哪种类型,每个类如果碰到它不能处理的请求只要放弃
就可以。无疑这降低了类之间的耦合性。
缺点是效率低,因为一个请求的完成可能要遍历到最后才可能完成,当然也可以用树的概念
优化。 在Java AWT1.0 中,对于鼠标按键事情的处理就是使用CoR,到Java.1.1 以后,就
使用Observer 代替CoR
扩展性差,因为在CoR 中,一定要有一个统一的接口Handler.局限性就在这里。

16.Command

Command 定义
不少Command 模式的代码都是针对图形界面的,它实际就是菜单命令,我们在一个下拉菜单
选择一个命令时,然后会执行一些动作.
将这些命令封装成在一个类中,然后用户(调用者)再对这个类进行操作,这就是Command 模
式,换句话说,本来用户(调用者)是直接调用这些命令的,如菜单上打开文档(调用者),就直
接指向打开文档的代码,使用Command 模式,就是在这两者之间增加一个中间者,将这种直接
关系拗断,同时两者之间都隔离,基本没有关系了.
显然这样做的好处是符合封装的特性,降低耦合度,Command 是将对行为进行封装的典型模
式,Factory 是将创建进行封装的模式,
从Command 模式,我也发现设计模式一个"通病":好象喜欢将简单的问题复杂化, 喜欢在不
同类中增加第三者,当然这样做有利于代码的健壮性 可维护性 还有复用性.

如何使用?
具体的Command 模式代码各式各样,因为如何封装命令,不同系统,有不同的做法.下面事例
是将命令封装在一个Collection 的List 中,任何对象一旦加入List 中,实际上装入了一个
封闭的黑盒中,对象的特性消失了,只有取出时,才有可能模糊的分辨出:
典型的Command 模式需要有一个接口.接口中有一个统一的方法,这就是"将命令/请求封装
为对象":

public interface Command {
public abstract void execute ( );
}

public class Engineer implements Command {
public void execute( ) {
//do Engineer's command
}
}
public class Programmer implements Command {
public void execute( ) {
//do programmer's command
}
}
public class Politician implements Command {
public void execute( ) {
//do Politician's command
}
}

public class producer{
public static List produceRequests() {
List queue = new ArrayList();
queue.add( new Engineer() );
queue.add( new Politician() );
queue.add( new Programmer() );
return queue;
}
}
public class TestCommand {
public static void main(String[] args) {
List queue = Producer.produceRequests();
for (Iterator it = queue.iterator(); it.hasNext(); )
//取出List 中东东,其他特征都不能确定,只能保证一
个特征是100%正确,
// 他们至少是接口Command 的"儿子".所以强制转换
类型为接口Command
((Command)it.next()).execute();
}
}

17.State/Strategy

State 的定义: 不同的状态,不同的行为;或者说,每个状态有着相应的行为.

何时使用?
State 模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else
进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取
State 模式了.
不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在数
据库系统中出现频率比较高,我们经常会在一个数据表的尾部,加上property 属性含义的字
段,用以标识记录中一些特殊性质的记录,这种属性的改变(切换)又是随时可能发生的,就有
可能要使用State.

--------------------------------------------------

Strategy 是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个
个封装成单独的类.

18.Mediator

Mediator 定义:
用一个中介对象来封装一系列关于对象交互行为.

为何使用Mediator?
各个对象之间的交互操作非常多;每个对象的行为操作都依赖彼此对方,修改一个对象的行
为,同时会涉及到修改很多其他对象的行为,如果使用Mediator 模式,可以使各个对象间的
耦合松散,只需关心和 Mediator 的关系,使多对多的关系变成了一对多的关系,可以降低系
统的复杂性,提高可修改扩展性.

public interface Mediator { }

public class ConcreteMediator implements Mediator {
//假设当前有两个成员.
private ConcreteColleague1 colleague1 = new ConcreteColleague1();
private ConcreteColleague2 colleague2 = new ConcreteColleague2();
...
}

public class Colleague {
private Mediator mediator;
public Mediator getMediator() {
return mediator;
}
public void setMediator( Mediator mediator ) {
this.mediator = mediator;
}
}
public class ConcreteColleague1 { }
public class ConcreteColleague2 { }

每个成员都必须知道Mediator,并且和 Mediator 联系,而不是和其他成员联系.
至此,Mediator 模式框架完成,可以发现Mediator 模式规定不是很多,大体框架也比较简单,
但实际使用起来就非常灵活.
Mediator 模式在事件驱动类应用中比较多,例如界面设计GUI.;聊天,消息传递等,在聊天应
用中,需要有一个MessageMediator,专门负责request/reponse 之间任务的调节.
MVC 是J2EE 的一个基本模式,View Controller 是一种Mediator,它是Jsp 和服务器上应用
程序间的Mediator.

19.Interpreter

Interpreter 定义:
定义语言的文法 ,并且建立一个解释器来解释该语言中的句子.

20.Visitor

Visitor 定义
作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作
用于这些对象的新操作.

posted on 2012-08-22 16:53  斗哥哥  阅读(246)  评论(0编辑  收藏  举报