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

Decorator(装饰器模式)

目的:

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

适用性:

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

简单解释

当有一个已经完成的系统,其中类和对象的关系的错综复杂的,此时若想给某类对象添加一些额外的属性或方法(状态或职责),可能会引起其他地方的报错。

因此就需要在目标类的同一层级,新增一个与目标类继承同一父类的抽象修饰器类(方便向上转型),并且在其中包含有父类类型的一个引用(方便接收目标对象)。

修饰器下一层的具体实现类 ConcreteDecorator 继承 Decorator,并负责具体的职责添加,可以选择添加状态(属性) addedState 或者添加行为(方法) AddedBehavior()。

而在使用中,由于 ConcreteDecorator 继承了 Decorator, Decorator 又继承自 Component ,因此对于 ConcreteDecorator 可以直接向上转型到 Component。

目标对象 ConcreteComponent 也可以向上转型到 Component,此时两者类型相同,可直接进行 "=" 操作,实现了目标对象的"职责更新"。

(但其实此时,实现更新后的新对象其结构已经不是左边的单一层级了,而是右边的修饰器的多层级了。在内存中已经是两个不同地址的引用了)

代码示例

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

java 复制代码
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 + "的职责是:学习");
	}
}
  • 输出:张三的职责是:学习

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

java 复制代码
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 + "的职责是:学习 ");
	}
}

输出:

张三的职责是:学习


张三的职责是:学习 读书


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

参考

B站 zst_2001 软考设计模式

相关推荐
果汁华15 分钟前
java学习连续打卡30天(1)
java
武子康43 分钟前
Java-171 Neo4j 备份与恢复 + 预热与执行计划实战
java·开发语言·数据库·性能优化·系统架构·nosql·neo4j
m0_639817151 小时前
基于springboot火锅店管理系统【带源码和文档】
java·spring boot·后端
会编程的林俊杰2 小时前
SpringBoot项目启动时的依赖处理
java·spring boot·后端
一叶飘零_sweeeet2 小时前
深度拆解汽车制造系统设计:用 Java + 设计模式打造高扩展性品牌 - 车型动态生成架构
java·设计模式·工厂设计模式
王家羽翼-王羽3 小时前
nacos 3.1.0 运行主类报错 com.alibaba.cloud.nacos.logging.NacosLoggingAppRunListener
java
影子24013 小时前
oralce创建种子表,使用存储过程生成最大值sql,考虑并发,不考虑并发的脚本,plsql调试存储过程,java调用存储过程示例代码
java·数据库·sql
阿波罗尼亚3 小时前
设计原则(一)Head First设计模式
设计模式
武子康3 小时前
Java-172 Neo4j 访问方式实战:嵌入式 vs 服务器(含 Java 示例与踩坑)
java·服务器·数据库·sql·spring·nosql·neo4j