- 装饰模式:一种常见的模式,动态地给一个对象添加一些额外的职责,就增加功能来看,装饰模式比生成子类更加灵活。
- 装饰模式的通用类图如下:
- Component抽象构件:Component是一个接口或者是 抽象类 ,就是我们需要装饰的核心对象。在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component构件。
- ConcreteComponent是Component接口或抽象类的实现。
- Decrator装饰角色:一般是一个抽象类,实现接口或者抽象方法,其属性必然有一个private变量指向Component抽象构件。
- ConcreteDecrator具体装饰类。
其通用类图源码如下:
public abstract class Component {
public abstract void doSomething();
}
public class ConcreteComponent extends Component{
@ Override
public void doSomething() {
// TODO Auto-generated method stub
System.out.println("this is a ConcreteComponent");
}
}
public abstract class Decrator extends Component{
private Component component = null;
public Decrator(Component com){
this.component = com;
}
@Override
public void doSomething(){
this.component.doSomething();
}
}
public class ConcreteDecrator1 extends Decrator{
public ConcreteDecrator1(Component com) {
super(com);
// TODO Auto-generated constructor stub
}
public void doSomething() {
// TODO Auto-generated method stub
this.method1();
super.doSomething();
}
private void method1(){
System.out.println("this is a ConcreteDecrator");
}
}
public class ConcreteDecrator2 extends Decrator{
public ConcreteDecrator2(Component com) {
super(com);
// TODO Auto-generated constructor stub
}
public void doSomething(){
super.doSomething();
this.method2();
}
private void method2(){
System.out.println("this is another ConcreteDecrator");
}
}
public class Client {
/**
* @param args
*/ public static void main(String[] args) {
// TODO Auto-generated method stub
Component component = new ConcreteComponent();
component = new ConcreteDecrator1(component);
component = new ConcreteDecrator2(component);
component.doSomething();
}
}
- 装饰模式的应用
- 最近刚刚过了双十一的网上购物狂潮,购买的商品也万里迢迢的飞奔而来,拿到快递那一刻的喜悦简直感觉自己就是世界上最幸福的,然而如果你买的是服装,相信你一定深有体会,为什么自己穿上就没有那种感觉了呢,冥思苦想,应该是商家对服装的装饰比较到位,下面我们就解析一下这种“差距”。
- 首先我们先看一下类图:
- Clothes类是一个抽象类,是我们在网上看到的各种服装的总称,它有一个展示其参数的方法parameter(),提供给买家参考。
- Coat类是服装中的具体的一件上衣。
- Decrator是抽象的装饰类,其中包括一个Clothes对象。
- Model具体装饰类,让时装模特穿上这个外套。
- Scarf具体的装饰类,为外套装饰一条围巾。
- 如下是类图的通用源码实现:
public abstract class Clothes { //展示服装信息 public abstract void parameter(); } public class Coat extends Clothes{ @Override public void parameter() { // TODO Auto-generated method stub System.out.println("this is a Coat"); System.out.println("It's size is XL"); System.out.println("It's color is dark blue"); } } public abstract class Decrator extends Clothes{ private Clothes clothes = null; public Decrator(Clothes clothes){ this.clothes = clothes; } @Override public void parameter(){ this.clothes.parameter(); } } public class Model extends Decrator{ public Model(Clothes clothes) { super(clothes); // TODO Auto-generated constructor stub } public void parameter(){ this.method2(); super.parameter(); } private void method2(){ System.out.println("A clothes model wears the coat"); } } public class Scarf extends Decrator{ public Scarf(Clothes clothes) { super(clothes); // TODO Auto-generated constructor stub } public void parameter() { // TODO Auto-generated method stub this.method1(); super.parameter(); } private void method1(){ System.out.println("this is a scarf to decrate the coat"); } } public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Clothes clothes = new Coat(); clothes = new Scarf(clothes); clothes = new Model(clothes); clothes.parameter(); } }
- 可怜了我们这些小白用户,不知道还能这么玩, 蓝瘦香菇 。
装饰模式的优点
- 装饰类和被装饰类可以独立发展,而不会相互耦合。如实例,服装类Clothes不需要知道装饰类Decrator,装饰类是从外部来扩展服装类的,而装饰类也不用知道具体的服装类。
- 装饰模式是一种继承关系的替代方案,装饰类Decrator不管装饰多少层,返回的对象还是Clothes,实现的还是is-a的关系。
- 装饰类可以动态扩展一个实现类的功能。如上述例子中,上衣有多个子类(Jacket、Shirt等),如果开发到中途,需求提出要改动Coat类,那可能对Coat的子类产生影响,而此时可以用装饰模式,通过建立CoatDecrator来修饰Coat类,相当于创建了一个新类,原有程序没有变更,通过扩展满足了需求。
装饰模式的缺点
- 多层装饰比较复杂,需要尽量减少装饰类的数量,以便降低系统的复杂度。