装饰模式


装饰模式

装饰模式:一种常见的模式,动态地给一个对象添加一些额外的职责,就增加功能来看,装饰模式比生成子类更加灵活。
装饰模式的通用类图如下:

 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();
}

}

View Code

装饰模式的应用

最近刚刚过了双十一的网上购物狂潮,购买的商品也万里迢迢的飞奔而来,拿到快递那一刻的喜悦简直感觉自己就是世界上最幸福的,然而如果你买的是服装,相信你一定深有体会,为什么自己穿上就没有那种感觉了呢,冥思苦想,应该是商家对服装的装饰比较到位,下面我们就解析一下这种“差距”。

首先我们先看一下类图:

 

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();
}

}

View Code
可怜了我们这些小白用户,不知道还能这么玩,蓝瘦香菇。

装饰模式的优点

装饰类和被装饰类可以独立发展,而不会相互耦合。如实例,服装类Clothes不需要知道装饰类Decrator,装饰类是从外部来扩展服装类的,而装饰类也不用知道具体的服装类。
装饰模式是一种继承关系的替代方案,装饰类Decrator不管装饰多少层,返回的对象还是Clothes,实现的还是is-a的关系。
装饰类可以动态扩展一个实现类的功能。如上述例子中,上衣有多个子类(Jacket、Shirt等),如果开发到中途,需求提出要改动Coat类,那可能对Coat的子类产生影响,而此时可以用装饰模式,通过建立CoatDecrator来修饰Coat类,相当于创建了一个新类,原有程序没有变更,通过扩展满足了需求。

装饰模式的缺点

多层装饰比较复杂,需要尽量减少装饰类的数量,以便降低系统的复杂度。

声明:DungCry.|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 装饰模式


以此热爱,以此谋生。
Le vent se lève, il faut tenter de vivre