• 设计模式——装饰器模式


    设计模式——装饰器模式

    定义: 例如: 一个快餐店当中有炒饭和炒面, 炒饭和炒面又分为鸡蛋炒饭/面和培根炒饭/面, 一般写法是, 定义一个快餐类然后创建一个炒饭/面类继承快餐类, 再创建鸡蛋/培根 炒饭/面类继承炒饭/面类, 这样会让系统变得臃肿而且不灵活, 每次新增快餐都要创建很多类. 装饰器模式可以在不改变现有的结构模式下, 动态的给对象增加一些职责.

    结构:

    1. 抽象构件: 一个抽象接口, 用于规范准备接收附加责任的对象
    2. 具体构件: 实现抽象构件, 通过装饰为角色添加一些职责
    3. 抽象装饰: 继承或实现抽象构件, 并且包含具体构件的实例, 可以通过子类扩展具体构件的功能
    4. 具体装饰: 实现抽象装饰的相关方法, 并给具体构件对象添加附加责任

    实现:

    例: 一个快餐店当中有炒饭和炒面, 炒饭和炒面又分为鸡蛋炒饭/面和培根炒饭/面

    抽象构件

    /**
     * 抽象构件
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public abstract class FastFood {
    
        private double price;
    
        private String desc;
    
        public abstract double cost();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    具体构件

    /**
     * 具体构件
     */
    public class FriedNoodles extends FastFood {
    
        public FriedNoodles() {
            super(15, "炒面");
        }
    
        public double cost() {
            return getPrice();
        }
    }
    
    /**
     * 具体构件
     */
    public class FriedRice extends FastFood {
    
        public FriedRice() {
            super(10, "炒饭");
        }
    
        public double cost() {
            return getPrice();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    抽象装饰

    /**
     * 抽象装饰
     */
    @Data
    public abstract class Garnish extends FastFood {
    
        private FastFood fastFood;
    
        public Garnish(FastFood fastFood, double price, String desc) {
            super(price, desc);
            this.fastFood = fastFood;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    具体装饰

    /**
     * 具体装饰
     */
    public class Egg extends Garnish {
    
        public Egg(FastFood fastFood) {
            super(fastFood, 2, "鸡蛋");
        }
    
        public double cost() {
            return getPrice() + getFastFood().cost();
        }
    
        @Override
        public String getDesc() {
            return super.getDesc() + getFastFood().getDesc();
        }
    }
    
    
    /**
     * 具体装饰
     */
    public class Bacon extends Garnish {
    
        public Bacon(FastFood fastFood) {
            super(fastFood, 4, "培根");
        }
    
        public double cost() {
            return getPrice() + getFastFood().cost();
        }
    
        @Override
        public String getDesc() {
            return super.getDesc() + getFastFood().getDesc();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    Main

    /**
     * 装饰器模式
     *
     * 优点:
     * 1. 带来比继承更加灵活的扩展功能, 使用更加方便,
     *    通过组合不同的装饰对象获取不同行为状态的多样化结果
     *
     * 2. 装饰类和被装饰类可以独立发展, 不相互耦合, 是继承模式的一个替代模式,
     *    装饰器模式可以动态扩展一个实现类的功能
     */
    public class Main {
        public static void main(String[] args) {
            FastFood friedRice = new FriedRice();
            System.out.println(friedRice.getDesc() + ": " + friedRice.cost());
    
            FastFood eggFriedRice = new Egg(friedRice);
            System.out.println(eggFriedRice.getDesc() + ": " + eggFriedRice.cost());
    
            FastFood baconEggFriedRice = new Bacon(eggFriedRice);
            System.out.println(baconEggFriedRice.getDesc() + ": " + baconEggFriedRice.cost());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    使用场景:

    1. 当不能采用继承方式对系统进行扩充或者采用继承不利于维护时
      不能采用继承方式的情况
      1. 第一类是系统中存在大量独立的扩展, 为支持每一种组合产生大量的子类
      2. 第二类是因为类定义不能继承
    2. 在不影响其他对象的情况下, 动态透明的给单个对象添加职责
    3. 当对象的功能要求可以动态添加, 也可以动态撤销时
  • 相关阅读:
    网络通信知识地图
    代码随想录算法训练营第23期day24|回溯算法理论基础、77. 组合
    Mybatis-Plus
    电脑文件如何实时备份?
    Python技法:浮点数取整、格式化和NaN处理
    设计原则与思想
    Rust(16):结构体方法
    2023 年最新企业微信官方会话机器人开发详细教程(更新中)
    leetcode -658--找到 K 个最接近的元素
    非自交任意多边形与矩形框的交集面积计算方法
  • 原文地址:https://blog.csdn.net/KobeSacre/article/details/126689691