前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >05-03-设计模式 装饰模式

05-03-设计模式 装饰模式

作者头像
彼岸舞
发布2022-05-28 09:22:25
2070
发布2022-05-28 09:22:25
举报
文章被收录于专栏:java开发的那点事

星巴克咖啡订单项目(咖啡馆)

  1. 咖啡种类/单品咖啡:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)
  2. 调料:Milk、Soy(豆浆)、Chocolate
  3. 要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
  4. 使用OO的来计算不同种类咖啡的费用:客户可以点单品咖啡,也可以单品咖啡+调料组合。

方案一实现

其实这个就是穷举, 将所有的方式拼接

分析问题

  1. Drink是一个抽象类,表示饮料
  2. des就是对咖啡的描述,比如咖啡的名字
  3. cost()方法就是计算费用,Drink类中做成一个抽象方法.
  4. Decaf就是单品咖啡,继承Drink,并实现cost
  5. Espress&&Milk就是单品咖啡+调料,这个组合很多
  6. 问题:这样设计,会有很多类,当我们增加一个单品咖啡,或者一个新的调料,类的数量就会倍增,就会出现类爆炸

方案二实现

前面分析到方案1因为咖啡单品+调料组合会造成类的倍增,因此可以做改进,将调料内置到Drink类,这样就不会造成类数量过多。从而提高项目的维护性(如图)

说明:milk,soy,chocolate可以设计为Boolean,表示是否要添加相应的调料.

分析问题

  1. 方案2可以控制类的数量,不至于造成很多的类
  2. 在增加或者删除调料种类时,代码的维护量很大
  3. 考虑到用户可以添加多份调料时,可以将hasMilk返回一个对应int
  4. 考虑使用装饰者模式

装饰者模式定义

  1. 装饰者模式: 动态的将新功能附加到对象上, 在对象功能扩展方面, 它比继承更有弹性, 装饰者模式也体现了开闭原则
  2. 这里提到的动态的将新功能附加到对象和ocp原则, 在后面的应用实例上会以代码的形式体现

装饰者模式原理

  • 装饰者模式就像打包一个快递
    • 主体:比如:陶瓷、衣服(Component)//被装饰者
    • 包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)
  • Component主体:比如类似前面的Drink
  • ConcreteComponent和Decorator
    • ConcreteComponent:具体的主体,比如前面的各个单品咖啡
  • Decorator:装饰者,比如各调料.

在如图的Component与ConcreteComponent之间,如果ConcreteComponent类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。

装饰者模式解决方案

装饰者模式下的订单: 2份巧克力+一份牛奶的LongBlack

装饰者模式解决方案代码实现

代码语言:javascript
复制
package com.flower.zhaungshizhe;

import lombok.AllArgsConstructor;
import lombok.Data;

public class TestMain {
    public static void main(String[] args) {
        // 装饰者模式下订单 2份巧克力 + 一份牛奶 + 一份LongBlank咖啡
        // 一份LongBlank咖啡
        Drink drink = new LongBlack();
        // 添加一份牛奶
        drink = new Milk(drink);
        // 添加一份巧克力
        drink = new Chocolate(drink);
        // 添加二份巧克力
        drink = new Chocolate(drink);
        float cost = drink.cost();
        System.out.println("价格为:" + cost);
        System.out.println(drink.getDes());
    }
}

/**
 * 饮用抽象类
 */
@Data
abstract class Drink{
    public String des;
    private float price = 0.0F;
    // 计算价格
    public abstract float cost();
}

/**
 * 咖啡类
 */
class Coffee extends Drink{

    @Override
    public float cost() {
        return super.getPrice();
    }
}

/**
 * 意大利咖啡
 */
class Espresso extends Coffee{
    public Espresso(){
        setDes("意大利咖啡");
        setPrice(6.0F);
    }
}
/**
 * 美式咖啡
 */
class LongBlack extends Coffee{
    public LongBlack(){
        setDes("美式咖啡");
        setPrice(10.0F);
    }
}

/**
 * 装饰者
 */
@AllArgsConstructor
class Decorator extends Drink{
    // 被装饰者
    private Drink drink;
    @Override
    public float cost() {
        // 自身价格 + coffee价格
        return super.getPrice() + drink.cost();
    }

    @Override
    public String getDes() {
        return super.getDes() + " " + super.getPrice() + " && " + drink.getDes() + " " + drink.getPrice();
    }
}

/**
 * 巧克力
 */
class Chocolate extends Decorator{
    public Chocolate(Drink drink) {
        super(drink);
        setDes("巧克力调味品");
        setPrice(3.0F);
    }
}

/**
 * 牛奶
 */
class Milk extends Decorator{
    public Milk(Drink drink) {
        super(drink);
        setDes("牛奶调味品");
        setPrice(2.0F);
    }
}

类图

源码剖析

JDK源码

Java的IO结构FilterInputStream就是一个装饰者

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 星巴克咖啡订单项目(咖啡馆)
  • 方案一实现
  • 分析问题
  • 方案二实现
  • 分析问题
  • 装饰者模式定义
  • 装饰者模式原理
  • 装饰者模式解决方案
  • 装饰者模式下的订单: 2份巧克力+一份牛奶的LongBlack
  • 装饰者模式解决方案代码实现
  • 类图
  • 源码剖析
    • JDK源码
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档