近日软件构造的实验中介绍了一种特殊的设计模式-Decorator
,之所以说它特殊,是因为Decorator
(装饰器)设计模式是一种自己Delegates
(委派)自己的模式,同时正是因为这种属性使得它变得相对其他模式难以理解。
提示:需要先了解Delegation!!!
Decorator模式用于设计描述多种特性,类似于穿衣服,每件衣服会有不同的特性,比如保暖的最内层衣服,正常的打底衣服,以及外面用来装逼的风衣(划掉)。那可能有人马上想到,那直接继承啊,一个父类,几个子类,完全够应付了。确实,但是考虑到可能会有很多子类,而且可能每次你并不会用到所有的子类,比如夏天你可能只需要一条小裤衩,这样一个小裤衩也会是一个继承分支。这样一来就会导致组合爆炸的问题,即可能会产生一颗很大的继承树,以及大量的重复性代码,其可复用性很低,修改的代价高昂,即每次需要修改所有的同样代码的子类,或者增加新的子类十分麻烦。这样Decorator模式应运而生,即一种可以随意组合穿搭的模式。这种模式如何设计呢?其UML图如下:
事实上当一个事物有较多属性才会显出这个模式的优点,为了介绍方便,这里只有两个特性。
1.首先看接口A
,A
是一个接口,里面只有一个方法print(),即打印一个字符串。
public interface A {
public void print();
}
2.然后便是一个很简单的实现类concreteA
实现了这个接口。里面实现了唯一的方法,并打印出一个字符串“concreteA”
public class concreteA implements A{
@Override
public void print() {
System.out.println("concrete A");
}
}
接下来便是对于这个concreteA
的装饰部分!!!
3.首先是一个抽象类B
实现了接口A
,并且委派concreteA
给自己做了print这个事情。
(1)首先在里面定义一个concreteA
类型的参数tmp
,并把它传入B
中。
(2)实现接口A
的print方法,这里直接使用concreteA
的实现而不需要自己做。
public abstract class B implements A{
A tmp;
public B(A tmp) {
this.tmp = tmp;
}
@Override
public void print() {
tmp.print();
}
}
4.假设concreteA
有两个属性,其中一个为dA
,这里dA
继承抽象类B
,那么直接使用B
中的tmp
为自己的参数。然后直接使用父类B
的print方法作为自己print方法的基础实现,并增加一个特性,即输出“dA”。
public class dA extends B {
public dA(A tmp) {
super(tmp);
}
@Override
public void print() {
super.print();
System.out.println("dA");
}
}
5.同理实现另外一个特性dB
,增加自己的特性,输出“dB”。
public class dB extends B{
public dB(A tmp) {
super(tmp);
}
@Override
public void print() {
super.print();
System.out.println("dB");
}
}
那么写到这里,整个设计已经完成,接下来看看如何使用。
(1)首先实例化一个基础的实现,即concreteA
。
(2)然后可以使用其特性类包装它,任意顺序都可以(指superman内裤反穿???)。
public class DMain {
public static void apart() {
System.out.println("\n----------------------------------------------------------\n");
}
public static void main(String[] args) {
A tmp1 = new concreteA();//基础的实现
tmp1.print();
apart();
A tmp2 = new dA(new concreteA());//包装了dA特性
tmp2.print();
apart();
A tmp3 = new dB(new concreteA());//包装了dB特性
tmp3.print();
apart();
A tmp4 = new dA(new dB(new concreteA()));//同时包装了dB,dA特性
tmp4.print();
}
}
让我们看看它的输出
concrete A
----------------------------------------------------------
concrete A
dA
----------------------------------------------------------
concrete A
dB
----------------------------------------------------------
concrete A
dB
dA
仓促之间,如有错误欢迎指出。