• 如何搞定五花八门的咖啡饮料?-装饰者模式


    咖啡价格

    设计一

    image

    • Beverage(饮料)是一个抽象类,店内所提供的饮料都必须继承自此类。
    • description的实例变量,由每个子类设置,用来描述饮料。
    • 利用getDescription()方法返回此叙述。
    • cost()方法是抽象的,子类必须定义自己的实现。

    上述设计会导致类爆炸。

    设计二

    image

    • 实例变量增加各种调料的新的布尔值。
    • cost()不再是一个抽象方法,而是提供了cost()的实现,让它计算要加入各种饮料的调料价钱。子类仍将覆盖cost(),但是会调用超类的cost(),计算出基本饮料加上调料的价钱。

    利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

    开放-关闭原则

    类应该对扩展开放,对修改关闭。

    我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。

    装饰者模式

    目前遇到的问题:

    • 类数量爆炸
    • 设计死板
    • 基类加入新功能并不适用于所有的子类

    我们要以饮料为主体,然后在运行时以调料来“装饰”(decorate)饮料。比方说,如果顾客想要摩卡和奶泡深焙咖啡,那么要做的是:

    • 拿一个深焙咖啡(DarkRoast)对象
    • 以摩卡(Mocha)对象装饰它
    • 以奶泡(whip)对象装饰它
    • 调用cost()方法,并依赖委托(delegate)将调料的价钱加上去
    1. 装饰者和被装饰者对象有相同的超类型
    2. 可以用一个或多个装饰者包装一个对象
    3. 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的
    4. 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢地装饰者来装饰对象

    装饰者模式定义:

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

    image

    装饰咖啡

    image

    public abstract class Beverage {
        String description = "Unknown Beverage";
    
        public String getDescription(){
            return description;
        }
    
        public abstract double cost();
    }
    
    public abstract class CondimentDecorator extends  Beverage{
        @Override
        public abstract String getDescription();
    }
    
    public class Espresso extends Beverage {
        public Espresso(){
            description = "Espresso";
        }
    
        @Override
        public double cost(){
            return 1.99;
        }
    }
    
    public class HouseBlend extends Beverage {
        public HouseBlend(){
            description = "HouseBlend";
        }
    
        @Override
        public double cost(){
            return 0.89;
        }
    }
    
    public class Mocha extends CondimentDecorator {
        Beverage beverage;
    
        public Mocha(Beverage beverage){
            this.beverage = beverage;
        }
        @Override
        public String getDescription() {
            return beverage.getDescription()+",Mocha";
        }
    
        @Override
        public double cost() {
            return 0.2 + beverage.cost();
        }
    }
    
    public class StarbuzzCoffee {
        public static void main(String[] args) {
            Beverage beverage = new Espresso();
            System.out.println(beverage.getDescription() + " $"+beverage.cost());
    
            Beverage beverage2 = new HouseBlend();
            beverage2 = new Mocha(beverage2);
            beverage2 = new Mocha(beverage2);
            System.out.println(beverage2.getDescription()+" $"+beverage2.cost());
        }
    }
    

    装饰者-Java I/O

    image

    使用装饰者模式,把输入流的所有大写字符转换成小写。

    /**
     * @ClassName LowerCaseInputStream
     * @Author jia_xx
     * @Date 2022/9/30 15:22
     */
    public class LowerCaseInputStream extends FilterInputStream {
    
        protected LowerCaseInputStream(InputStream in) {
            super(in);
        }
    
        @Override
        public int read() throws IOException {
            int c = super.read();
            if(c == -1){
                return c;
            }
            return Character.toLowerCase((char)c);
        }
    
        @Override
        public int read(byte[] b,int offset,int len) throws IOException {
            int result = super.read(b,offset,len);
            for(int i = offset;i= 0){
                    System.out.print((char)c);
                }
            }finally {
                in.close();
            }
    
        }
    }
    
  • 相关阅读:
    MySQL索引失效场景,索引优化,索引原理
    Java8的stream之groupingBy()分组排序
    y44.第三章 Kubernetes从入门到精通 -- k8s 资源对象(十七)
    DXF笔记:多义线线宽的绘制思路
    设计模式简介
    linux平台下一个好用的并行压缩工具(cpu核数越多越快,比tar -j可以快很多倍)
    linux系统中通配符与常用转义字符
    谨以此篇纪念我的csdn创作两周年
    ②【Maven】从0上手Maven的安装与配置 - 最全教程 (下载 + 配置 + 环境变量 )
    Dense embedding model 和 sparse embedding model 对比
  • 原文地址:https://blog.csdn.net/wozaibohaibian/article/details/127098993