• 设计模式之装饰者模式


    什么是装饰者模式

    装饰者模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象

    角色

    • 抽象构件角色(Component):给出一个抽象接口,以规范准备接收附加责任的对象
    • 具体构件(Concrete Component)角色:定义一个想要接收附加责任的类
    • 装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口
    • 具体装饰(Concrete Decorator)角色:负责给构件对象加上附加的责任

    抽象构件角色

    用动物抽象类作为抽象构件角色,动物会移动,和咬

    public abstract class Animal {
        public abstract void move();
    
        public abstract void bite();
    }
    
    

    具体构件角色

    用会跑会咬的狗狗类作为具体构件角色

    public class Dog extends Animal {
    
        @Override
        public void move() {
            System.out.println("狗子跑起来吧。。。。。");
        }
    
        @Override
        public void bite() {
            System.out.println("狗子生气了,咬你。。。。。");
        }
    }
    

    装饰角色

    动物装备

    public abstract class AnimalEquipment extends Animal {
        private Animal animal;
    
        public AnimalEquipment(Animal animal) {
            this.animal = animal;
        }
    
        @Override
        public void move() {
            beforeMove();
            animal.move();
            afterMove();
        }
    
        @Override
        public void bite() {
            beforeBite();
            animal.bite();
            afterBite();
        }
    
        // 移动前的能力增强
        protected abstract void beforeMove();
    
        // 移动后的能力增强
        protected abstract void afterMove();
    
        // 咬你前的能力增强
        protected abstract void beforeBite();
    
        // 咬你后的能力增强
        protected abstract void afterBite();
    }
    

    具体装饰角色

    动物加速装备

    public class AnimalAcceleratorEquipment extends AnimalEquipment {
        // 定义被修饰者
        public AnimalAcceleratorEquipment(Animal animal) {
            super(animal);
        }
    
    
        @Override
        protected void beforeMove() {
            System.out.println("打开加速引擎......");
        }
    
        @Override
        protected void afterMove() {
            System.out.println("关闭加速引擎......");
        }
    
        @Override
        protected void beforeBite() {
    
        }
    
    
        @Override
        protected void afterBite() {
    
        }
    
    }
    

    动物保护装备

    public class AnimalProtectionEquipment extends AnimalEquipment {
        // 定义被修饰者
        public AnimalProtectionEquipment(Animal animal) {
            super(animal);
        }
    
        @Override
        protected void beforeMove() {
    
        }
    
        @Override
        protected void afterMove() {
    
        }
    
        @Override
        protected void beforeBite() {
            System.out.println("安装合金牙套");
        }
    
        @Override
        protected void afterBite() {
            System.out.println("取下合金牙套");
        }
    }
    

    测试

    public class Client {
        public static void main(String[] args) {
            System.out.println("一只善良小狗子散步中。。。。。");
            Animal animal = new Dog();
            System.out.println("一只凶猛大狗出现,前来欺负善良小狗。。。。。");
            System.out.println("赶紧为善良小狗装上保护装备,反击的时候到了。。。。。");
            animal = new AnimalProtectionEquipment(animal);
            animal.bite();
            System.out.println("糟糕了,有点过了,跑路吧,小狗子移动太慢了,装上加速装备。。。。。");
            animal = new AnimalAcceleratorEquipment(animal);
            animal.move();
        }
    }
    
    一只善良小狗子散步中。。。。。
    一只凶猛大狗出现,前来欺负善良小狗。。。。。
    赶紧为善良小狗装上保护装备,反击的时候到了。。。。。
    安装合金牙套
    狗子生气了,咬你。。。。。
    取下合金牙套
    糟糕了,有点过了,跑路吧,小狗子移动太慢了,装上加速装备。。。。。
    打开加速引擎......
    狗子跑起来吧。。。。。
    关闭加速引擎......
    

    装饰模式的总结

    主要优点
    • 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加;
    • 可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类;
    • 可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象;
    • 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类的具体装饰类,原有类库代码无需改变,符合“开闭原则”
    主要缺点
    • 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用很多的系统资源,在一定程序上影响程序的性能;
    • 装饰模式提供了一种比继承更加灵活机动的解决方案,但同时也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐
  • 相关阅读:
    tomcat在idea上的配置
    mybatis标签详解,一篇就够了
    5.12.webrtc接口调用过程
    Leetcode 0946. 验证栈序列
    win7连接打印机0x0000011b错误的解决办法
    文件I/O_02文件描述符fd
    独立站即web3.0,国家“十四五“规划要求企业建数字化网站!
    海外代购系统/代购网站怎么搭建——源码解析
    Python基础入门篇【27】--python基础入门练习卷C
    ​300+篇文献!一文详解基于Transformer的多模态学习最新进展
  • 原文地址:https://blog.csdn.net/qq_42582773/article/details/127105959