• 尚硅谷设计模式学习(九)装饰者模式


    以咖啡订单引入装饰者模式

    • 咖啡种类:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)
    • 调料:Milk、Soy(豆浆)、Chocolate

    客户可以点单品咖啡,也可以单品咖啡+调料组合。

    方案一

    比较差的设计样例,耦合度过高。

    如果说要添加扩展新的单品咖啡或者组合口味的咖啡,类的数量增加,就会引发"类爆炸"。

     方案二

    将调料内置到Drink类,不会造成类数量过多。

    但是,添加或者删除调味品的种类时,需要改动维护。

    一、装饰者模式 

    1、基本介绍

    动态的将新功能附加到对象上

    在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)。

    装饰者模式原理

    装饰者模式就像打包一个快递

    • 主体:比如:陶瓷、衣服    (Component) //    被装饰者 
    • 包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator) 

    Component 主体:比如类似前面的  Drink

    ConcreteComponent:具体的主体, 比如前面的各个单品咖啡

    Decorato:装饰者,比如各调料

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

    2、代码实现 

    思路分析

    在这里插入图片描述  

    抽象类饮品

    1. public abstract class Drink {
    2. //对饮品的描述
    3. private String description;
    4. //价格
    5. private float price;
    6. //计算价格,由子类实现
    7. public abstract float cost();
    8. public void setDescription(String description) {
    9. this.description = description;
    10. }
    11. public String getDescription() {
    12. return description;
    13. }
    14. public void setPrice(float price) {
    15. this.price = price;
    16. }
    17. public float getPrice() {
    18. return price;
    19. }
    20. }

    缓冲类Coffee

    1. public class Coffee extends Drink{
    2. @Override
    3. public float cost() {
    4. return super.getPrice();
    5. }
    6. }

    两种Coffee

    1. public class LongBlackCoffee extends Coffee{
    2. public LongBlackCoffee(){
    3. setDescription("一份美式咖啡");
    4. setPrice(7.0f);
    5. }
    6. }
    1. public class ShortBlackCoffee extends Coffee {
    2. public ShortBlackCoffee(){
    3. setDescription("一份浓缩咖啡");
    4. setPrice(5.0f);
    5. }
    6. }

    装饰者Decorator

    1. //装饰者
    2. public class Decorator extends Drink{
    3. //被装饰者;
    4. private Drink drink;
    5. public Decorator(Drink drink){
    6. this.drink = drink;
    7. }
    8. @Override
    9. public float cost() {
    10. return super.getPrice() + drink.cost();
    11. }
    12. @Override
    13. public String getDescription(){
    14. return drink.getDescription() + " && " +
    15. super.getDescription() + super.getPrice();
    16. }
    17. }

    两种调味品

    1. public class Milk extends Decorator{
    2. public Milk(Drink drink) {
    3. super(drink);
    4. setDescription("一份牛奶");
    5. setPrice(2.0f);
    6. }
    7. }
    1. public class Chocolate extends Decorator{
    2. public Chocolate(Drink drink) {
    3. super(drink);
    4. setDescription("一份巧克力");
    5. setPrice(1.0f);
    6. }
    7. }

    模拟客户下单

    1. public class Client {
    2. public static void main(String[] args) {
    3. //两份巧克力+一份牛奶的美式咖啡;
    4. //1.先点美式咖啡;
    5. Drink result = new LongBlackCoffee();
    6. System.out.println("步骤一::" + result.getDescription());
    7. System.out.println("本次花费==>" + result.cost());
    8. //2.加份牛奶;
    9. result = new Milk(result);
    10. System.out.println("步骤二::" + result.getDescription());
    11. System.out.println("本次花费==>" + result.cost());
    12. //3.加份巧克力;
    13. result = new Chocolate(result);
    14. System.out.println("步骤三::" + result.getDescription());
    15. System.out.println("本次花费==>" + result.cost());
    16. //4.加份巧克力;
    17. result = new Chocolate(result);
    18. System.out.println("步骤四::" + result.getDescription());
    19. System.out.println("最终花费==>" + result.cost());
    20. }
    21. }

    输出

    步骤一::一份美式咖啡
    本次花费==>7.0
    步骤二::一份美式咖啡 && 一份牛奶2.0
    本次花费==>9.0
    步骤三::一份美式咖啡 && 一份牛奶2.0 && 一份巧克力1.0
    本次花费==>10.0
    步骤四::一份美式咖啡 && 一份牛奶2.0 && 一份巧克力1.0 && 一份巧克力1.0
    最终花费==>11.0

     二、装饰者模式在 JDK 应用的源码分析

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

    1. public class Test {
    2. public static void main(String[] args) throws IOException {
    3. DataInputStream dataInputStream = new DataInputStream(new FileInputStream("e:\\a.txt"));
    4. System.out.println(dataInputStream.read());
    5. dataInputStream.close();
    6. }
    7. }

    说明

    • InputStream 是抽象类,类似前面的Drink
    • FileInputStream是InputStream子类,类似前面的浓缩咖啡,美式咖啡
    • FilterInputStream是InputStream子类,类似前面的Decorator修饰者
    • DataInputStream是FilterInputStream子类,具体的修饰者,类似前面的Milk,Chocolate等
    • FilterInputStream类有protected  volatile InputStream  in; 即含被装饰者
    1. public class FilterInputStream extends InputStream {
    2. protected volatile InputStream in;
    3. protected FilterInputStream(InputStream var1) {
    4. this.in = var1;
    5. }

    分析得出在 JDK 的 IO 体系中,就是使用装饰者模式 

  • 相关阅读:
    操作系统实验 & bochs 环境配置
    AutoGPT:有手就会的安装教程
    随机森林算法介绍
    C++---基础语法入门
    Python高级进阶(1)----深入理解Python迭代器与生成器
    国外Twilio 发送sms短信
    盐加密的了解和shiro认证-SSM
    Container is running beyond memory limits
    nvm切换node版本
    程序员缓解工作压力的小窍门
  • 原文地址:https://blog.csdn.net/qq_51409098/article/details/126898823