首页 > 技术文章 > 装饰模式

zhanglei93 2016-11-18 11:10 原文


装饰模式


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

    •  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类,相当于创建了一个新类,原有程序没有变更,通过扩展满足了需求。
装饰模式的缺点
  • 多层装饰比较复杂,需要尽量减少装饰类的数量,以便降低系统的复杂度。

推荐阅读