本文所写都是自己的理解,可能会有错误,如果有错误请指出。
在编程中我们可能会遇到类似的情况:一个功能它有好多的步骤,不同的步骤没有一定的顺序,可以组合,但是不同的组合会产生不同的效果,如果我们针对每一种组合都需要写一个程序,那么可能我们会累死。另外在以后如果组合改变的时候,我们改变也很不容易。类比生活中的例子:我们在穿衣服的时候,可以任意搭配,但是如果我们将一个组合固定下来,那么我们穿衣服的时候就有很大的局限性。这就类似我们将程序的步骤组合在一个程序中。但是实际情况是,我们的衣服都是独立存在的,它们之间没有太多的依赖关系,我们想怎么穿就怎么穿。同样我们想在程序中实现类似的功能,那么装饰模式就是一个很好的选择。
就拿穿衣服来说,比如我们准备穿大T恤、跨裤、破球鞋,可能我们在一个程序中写上穿了大T恤、跨裤、破球鞋,但是如果我们想转换一下顺序那么我们就得另外再写一个程序了。装饰模式解决了这样的一个问题,装饰模式可以动态的为一些对象增加一些职责,我们这里就是动态的穿衣服。这样说可能也不明白,先看代码吧。
这里有一个人的类,代表我们需要真正穿衣服的人,下面的服饰是一个父类,里面存储了一个我们穿衣服的人的实例,服饰类有三个子类分别代表不同的衣服。
package PersonDecorate;
public class Person
{
public Person() {
}
private String name;
public Person(String name){
this.setName(name);
}
public void Show(){
System.out.println("装扮的"+ name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package PersonDecorate;
class Finery extends Person {
protected Person component;
public void Decorate(Person component){
this.component = component;
}
@Override
public void Show(){
if(component != null){
component.Show();
}
}
}
package PersonDecorate;
class TShirts extends Finery {
public void Show(){
System.out.println("大T恤");
super.Show();
}
}
package PersonDecorate;
class BigTrousers extends Finery {
public void Show(){
System.out.println("跨裤");
super.Show();
}
}
package PersonDecorate;
class Sneakers extends Finery {
public void Show(){
System.out.println("破球鞋");
super.Show();
}
}
这个比较简单,几件衣服都是继承了服饰类,同样也继承了服饰类的Decorate方法,这个方法实际上就是设置穿衣服的人,但是这时候这个穿衣服的人可能已经穿了一些衣服了。这几件衣服的类中都重写了Show方法,同样也调用了父类的show方法,这样的目的是为了在原先的基础上加上一些新的逻辑,这里的原先是通过调用父类的Show方法实现的,新加的逻辑在我的程序中是输出对应的衣服,你同样可以实现别的逻辑。
下面给出主类:
package PersonDecorate;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Person person = new Person("SuperMan");
System.out.println("第一种:");
//创建三件衣服
Sneakers pqx = new Sneakers();
BigTrousers kk = new BigTrousers();
TShirts dtx = new TShirts();
pqx.Decorate(person);//这时候的person已经穿上了破球鞋
kk.Decorate(pqx);//这时候的person已经穿上了破球鞋、跨裤
dtx.Decorate(kk);//这时候的person已经穿上了破球鞋、跨裤、大T恤
//这个只是组合的一种,可以随便变换顺序
dtx.Show();
}
}
结果是
第一种:
大T恤
跨裤
破球鞋
装扮的SuperMan
这里需要注意这些Show方法调用顺序,例如在我们衣服类中Show方法是先输出还是先调用super.Show方法呢,它们的先后也决定了输出的结果。
另外我们同样也可以将Person类做成一个父类,然后再让我们实际穿衣服的人继承它,这样我们就可以给不同的角色的人穿衣服了。
我认为装饰模式主要的就是在装饰类(本程序是服饰类)中存储实际操做的对象,然后在通过子类为其添加一些业务逻辑,这里面类方法的调用顺序是比较混乱,但是如果搞明白了,这个设计模式也就学的比较透彻了。