装饰模式又名包装模式,是以对用户透明的方式动态的扩展原有类方法的功能。
说明
(1)对用户透明,就是说类的扩展不能改变原来的接口。
(2)继承也可以扩展类原来的方法,但那是静态的。装饰模式强调可以动态的拆卸
(3)是扩展原来的方法,而不是增加新方法。这样也保证了接口不变化,对用户透明
一面是一个UML
说明:红色为原来类的结构,白色为装饰类
原来有一个CDoor接口,有两个实现CHomeDoor,CShopDoor。现在要扩充open方法的功能。就另加了一个CDoorDecorator类,同样实现CDoor接口。但里面有一个CDoor的实现对象,各方法调用这个传入对象的方法实现接口的方法。而不是自己去做。仅加入对方法的扩充。
BranchManage (原有类接口)
package org.bluebea.gof.decorator;
public interface BranchManage {
public void saveBranch();
}
BranchManageImpl (原有类实现)
package org.bluebea.gof.decorator;
public class BranchManageImpl implements BranchManage {
public BranchManageImpl() {
}
public void saveBranch() {
System.out.println("-- " + "savebranch.");
}
}
BranchManageDec (扩展的父类)
package org.bluebea.gof.decorator;
public class BranchManageDec implements BranchManage {
protected BranchManage branchManage;
public BranchManageDec(BranchManage b) {
this.branchManage = b;
}
public void saveBranch() {
branchManage.saveBranch();
}
}
BranchManageDecFind (一个扩展)
package org.bluebea.gof.decorator;
public class BranchManageDecFind extends BranchManageDec {
public BranchManageDecFind(BranchManage b) {
super(b);
}
public void saveBranch() {
this.findBranch();
branchManage.saveBranch();
}
//扩展了一个功能.
private String findBranch() {
System.out.println("-- " + "BranchManageDecFind.findBranch().");
return null;
}
}
Test (测试)
package org.bluebea.gof.decorator;
/*
* 装饰模式
*/
public class Test {
public Test() {
}
public static void main(String args[]) {
BranchManage b = new BranchManageImpl();
BranchManage bf = new BranchManageDecFind(b);
b.saveBranch();
bf.saveBranch();
}
}
说明:
(1)调用时BranchManage bf = new BranchManageDecFind(b);
为保证了接口不变。如果写成BranchManageDecFind bf = new BranchManageDecFind(b); 就违背了装饰模式的目的。因为用户要声明 一个BranchManageDecFind 对象,对用户就不透明了。
(2)如果有多个装饰时,通常声明一个装饰的父类(BranchManageDec ),后面的各个装饰继承自这个父类。但如果只有一个装饰或比较少,可以不要装饰父类。下面是一个UML:
(3)因为BranchManageDec 构造时传入的是一个BranchMange接口的实现,所以可以将BranchManageDecFind 传入。这就实现了装饰 的叠加。可以将各个装饰进行排列组合,形成新的功能。