系统架构设计——设计模式之装饰者模式

11 篇文章 1 订阅
7 篇文章 0 订阅

许多模式是长期经验的实证,可通过提供扩展的方法来保护代码免于被修改。接下来我将介绍一下一个完全遵循开放-关闭原则的设计模式——装饰者模式它可以给爱用继承的人一个全新的设计眼界。——Head First 设计模式

装饰者模式的定义

动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案

应用场景

与之前的策略模式不同,装饰者模式是用来解决多方案的组合问题的。试想一下五个策略的任意组合有多少种呢?答案是: 251=31 种组合
策略模式的处理只能是实现单个的策略,而非他们的组合。那么,这时候就需要用上装饰者模式了。其实在java中,i/o的封装就是用的这种模式。

结构图如下

这里写图片描述

代码表示

现在我们从一个实际问题出发,体会一下装饰者模式的好处。
现实场景:在一家面馆中,面分为细面和宽面两种,价格分别为2元、2.5元。加入的料分为排骨和牛肉,价格分别为4元、4.5元。下面我们就使用装饰者模式实现他们的任意组合,并且如果加入别的种类,也不需要修改原先的代码。

1. 抽象构件(Component)角色,Noodles

package com.xiaocao.decorator;
/**
 * 顶层抽象类
 * 具有面的描述信息,和抽象的计算价格方法
 * @author 木小草
 *
 */
public abstract class Noddles {
    String description = "Unknown noodles";
    public String getDescription() {
        return description;
    }
    public abstract double cost();
}

2. 具体构件(Concrete Component)角色,宽面和细面

package com.xiaocao.decorator;
/**
 * 面A的实现类,宽面不好描述,索性用A来代替
 * @author 木小草
 *
 */
public class NoodlesA extends Noddles{
    public NoodlesA() {
        description = "宽面";
    }
    public double cost() {
        return 2.5;
    }
}
/*=============================================*/
package com.xiaocao.decorator;
/**
 * 面B的实现类
 * @author 木小草
 *
 */
public class NoodlesB extends Noddles{
    public NoodlesB() {
        description = "细面";
    }
    public double cost() {
        return 2.0;
    }

}

3. 装饰(Decorator)角色,各种料的抽象

package com.xiaocao.decorator;

/**
 * 这是装饰者共同实现的接口,也可以是抽象类
 * @author 小草
 *
 */
public abstract class CondimentDecorator extends Noddles{
    public abstract String getDescription();
}

4. 具体装饰(Concrete Decorator)角色,牛肉和排骨

package com.xiaocao.decorator;
/**
 * 装饰者的实现类,实现装饰部分,与其他装饰者没有关系
 * 如果添加装饰者可直接添加类即可,无需修改原有代码
 * @author 木小草
 *
 */
public class Beef extends CondimentDecorator{
    // 这一步很重要,这是装饰者模式的重要实现方式,即利用多态
    Noddles beverage;
    public Beef(Noddles beverage) {
        this.beverage = beverage;
    }
    public String getDescription() {
        return beverage.getDescription() + ",牛肉";
    }
    public double cost() {
        return 4.0 + beverage.cost();
    }

}
/*================================================*/
package com.xiaocao.decorator;
/**
 * 
 * @author 木小草
 *
 */
public class Chops extends CondimentDecorator{

    Noddles beverage;
    public Chops(Noddles beverage) {
        this.beverage = beverage;
    }

    public String getDescription() {
        return beverage.getDescription() + ",排骨";
    }
    public double cost() {
        return 3.5 + beverage.cost();
    }
}

5. 测试

package com.xiaocao.decorator;

public class Test {
    public static void main(String[] args) {
        // new一个宽面
        Noddles noodles = new NoodlesA();
        // 利用多态,将chops中的noodles被上一步的宽面赋值,相当于用chops装饰了上一步的宽面
        noodles = new Chops(noodles); 
        // 利用多态,将上一步的排骨宽面赋值给beef的noodles,相当于用beef又装饰了一遍
        noodles = new Beef(noodles);
        // 输出描述信息和计算价格一样,先调用beef的方法,然后通过noodles属性,一步步调用上一步的方法,实现动态装饰
        System.out.println(noodles.getDescription() + " $" + noodles.cost());
    }
}

运行结果如下
这里写图片描述

装饰者模式的认识

  1. 装饰者模式严格遵循了开放-关闭原则,如果我们想现在加入一个炸酱料,只需要新建一个炸酱的类继承Noodles,实现其中的方法即可。无需改动任何其他的类。如果在服务器运行中,服务器也不用重新编译,只需要重启一下就行。如果想实现连服务器也不用重启,则需要我们用到其他的知识实现,在这里就不讨论了。
  2. 装饰者模式充分利用了多态的特性,在分离了装饰行为和业务组合的同时,也让他们之间并没有具体感知。换句话说就是,每一个装饰者中的noodles属性成员只是一个接口,并不知道具体是宽面还是细面还是牛肉的等等。从这个层面讲,这也体现了单一职责原则和高内聚低耦合的设计思想。
  3. 还是那句话,”它可以给爱用继承的人一个全新的设计眼界“。

优缺点

优点

  1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
  2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点

  1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
  2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
  3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

注意:转载请标明,转自itboy-木小草
尊重原创,尊重技术。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值