• 设计模式——Decorator(装饰器模式)


    Decorator(装饰器模式)

    目的:

    动态地给一个对象添加一些额外的职责。

    适用性:

    在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

    简单解释

    当有一个已经完成的系统,其中类和对象的关系的错综复杂的,此时若想给某类对象添加一些额外的属性或方法(状态或职责),可能会引起其他地方的报错。
    因此就需要在目标类的同一层级,新增一个与目标类继承同一父类的抽象修饰器类(方便向上转型),并且在其中包含有父类类型的一个引用(方便接收目标对象)。
    在这里插入图片描述
    修饰器下一层的具体实现类 ConcreteDecorator 继承 Decorator,并负责具体的职责添加,可以选择添加状态(属性) addedState 或者添加行为(方法) AddedBehavior()。
    而在使用中,由于 ConcreteDecorator 继承了 Decorator, Decorator 又继承自 Component ,因此对于 ConcreteDecorator 可以直接向上转型到 Component。
    目标对象 ConcreteComponent 也可以向上转型到 Component,此时两者类型相同,可直接进行 “=” 操作,实现了目标对象的“职责更新”。
    (但其实此时,实现更新后的新对象其结构已经不是左边的单一层级了,而是右边的修饰器的多层级了。在内存中已经是两个不同地址的引用了)

    代码示例

    假设原有结构有 抽象类Person ,具体实现类 Student,其职责 Operation() 为学习。

    package decorator;
    
    public class DecoratorDemo {
    	public static void main(String[] args) {
    		Person zhangsan = new Student("张三");
    		zhangsan.Operation();
    	}
    }
    
    
    abstract class Person{ // Component
    	protected String name;
    	
    	abstract public void Operation(); // 职责
    }
    
    class Student extends Person{ // ConcreteComponent
    	public Student(String name) {
    		this.name = name;
    	}
    	
    	@Override
    	public void Operation() {
    		System.out.println(name + "的职责是:学习");
    	}
    }
    
    • 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
    • 输出:张三的职责是:学习

    现在要新增职责 “读书”,使用修饰器实现:

    package decorator;
    
    public class DecoratorDemo {
    	public static void main(String[] args) {
    		Person zhangsan = new Student("张三");
    		zhangsan.Operation();
    		
    		System.out.println("\n------------------");
    		// Decorator DecoratorA = new DecoratorA(zhangsan); //向上转型到Decorator
    		// Person DecoratorA = new DecoratorA(zhangsan); //向上转型到Person
    		
    		zhangsan = new DecoratorA(zhangsan); // Person类型相同,可以直接赋值
    		zhangsan.Operation();
    		
    		System.out.println("\n------------------");
    		zhangsan = new DecoratorB(zhangsan); // 继修饰器A添加“读书”后,在用修饰器B添加“写作业”
    		zhangsan.Operation();
    		
    	}
    }
    
    abstract class Decorator extends Person{ // 与目标类 Student 继承统一父类 Person
    	protected Person person; // 包含有父类类型的引用
    }
    
    class DecoratorA extends Decorator{
    	public DecoratorA(Person person) { // 构造函数接收目标对象
    		this.person = person;
    	}
    	
    	@Override
    	public void Operation() {
    		person.Operation(); // 原有的职责
    		System.out.print("读书 "); // 新增职责
    	}
    }
    
    class DecoratorB extends Decorator{
    	public DecoratorB(Person person) { // 构造函数接收目标对象
    		this.person = person;
    	}
    	
    	@Override
    	public void Operation() {
    		person.Operation(); // 原有的职责
    		System.out.print("写作业"); // 新增职责
    	}
    }
    
    abstract class Person{ // Component
    	protected String name;
    	
    	abstract public void Operation(); // 职责
    }
    
    class Student extends Person{ // ConcreteComponent
    	public Student(String name) {
    		this.name = name;
    	}
    	
    	@Override
    	public void Operation() {
    		System.out.print(name + "的职责是:学习 ");
    	}
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    输出:
    张三的职责是:学习
    ------------------
    张三的职责是:学习 读书
    ------------------
    张三的职责是:学习 读书 写作业

    参考

    B站 zst_2001 软考设计模式

  • 相关阅读:
    C++ 命名类型转换
    基于JAVA的网上花店销售系统的设计与实现(附:源码 论文 sql文件)
    Matlab生成visio可导入的矢量图
    表单基本操作
    LeetCode-380. Insert Delete GetRandom O(1) [C++][Java]
    举例说明自然语言处理(NLP)技术
    BUUCTF 九连环 1
    Scala入门教程
    Cox回归列线图(nomogram)的多种绘制方法
    常见的系统类别汇总——包含OA/CRM/ERP/SCM
  • 原文地址:https://blog.csdn.net/qq_41168765/article/details/133578120