HeadFirst设计模式之装饰者模式

本文介绍了装饰者模式的概念及其在星巴叉咖啡订单系统中的应用。通过对比传统设计与使用装饰者模式后的改进,阐述了装饰者如何避免类爆炸问题并实现代码的扩展性。文章通过代码示例展示了如何使用装饰者模式,强调其遵循开放-关闭原则,易于扩展而不修改原有代码。
摘要由CSDN通过智能技术生成

今天来梳理一下装饰模式,装饰模式能够在不修改任何底层代码的情况下,给你的(或者别人的)对象赋予新的职责。

装饰者模式

定义:

动态地将责任附加到对象上,若要扩展功能,装置社提供了比继承更有弹性的替代方案。
和之前一样,我们首先画出装饰者模式的类图。
在这里插入图片描述
如类图中所示,装饰者模式中有如下角色:

  1. component抽象构件接口:这是主题接口,装饰者和被装饰者都要实现的共同接口
  2. ConcreteComponent对象:这是被装饰者的具体实现类。
  3. Decorator:装饰者角色,负责赋予装饰者新的行为和职责
  4. ConcreteDecoratorA/B:具体的装饰者实现类。

装饰者模式实现案例

星巴叉咖啡订单系统

计入星巴叉系统需要设计一个咖啡馆订单项目,客户在点咖啡的时候每个人都有自己不同的需求,比如说有的客人可能需要无糖咖啡加奶、有的客人需要浓缩咖啡加巧克力加糖等。也就是说不同的客人可能点的主料不同,而配料也是可以随心所欲的搭配的。那应该怎么设计一个扩展性好、改动价格方便维护也方便的系统呢?

1.先看一个伸缩性和维护性都很差的案例。
在这里插入图片描述
该设计将饮料设计成一个超类,其中含有描述变量description用来说明顾客点的是什么饮料加了什么调料等。其中的抽象方法cost()用来返回该饮品所需要的花费。该抽象方法由具体的子类去实现,因为不同的咖啡以及所加调料的不同价钱也不同。
如果让所有的饮品都实现该基类就会出现出现下面这样的情况。
在这里插入图片描述
每一种咖啡根据所加的调料不同都衍生出一个具体的实现类,这样一个咖啡店恐怕要有维护成百上千个类,这对于程序维护者来说简直是地狱,以后每次新添加调料或者咖啡,都要修改或新增非常多的类。

2.下面是一种利用变量和继承来改进的设计
在这里插入图片描述
通过该设计超类cost()将计算所有调料的价钱,而子类覆盖过的cost()会扩展超类的功能,吧指定的饮料类型的价钱也加进去,同时还要加上调料的价钱。
该方法有效的解决了类爆炸的问题,但是仍然有很多问题,首先如果调料价钱的改变会使我们更改现有的代码,而且一旦出现新的调料,我们需要为每个类加上新的方法,并且需要改变超类中的cost()方法。而且每个饮料中都含有所有的调料,这显然不合适,以后如果咖啡店开发出茶饮,这样茶饮类里面有类似于whip(奶泡)这种调料显然不合适。

装饰者模式对系统进行改进

在这里插入图片描述
这里将调料抽离出来实现,实现CondimentDecorator接口或者基类。内部含有饮料的引用,这样就可以来装饰饮料类。
代码实现如下所示:
被装饰者基类

public abstract class Beverage {
   
    String description = "Unknown Beverage"; //Beverage是一个抽象类,有两个方法 getDescription()和cost()。
    
    public void setDescription(String description) {
   
        this.description = description ;
    }

    public String getDescription(){
   
        return description;         //getDescription已经在这实现了,但是cost()必须在子类中实现。
    }
    public abstract double cost
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值