目录
- 应用场景
- 涉及的角色和类(个人理解)
- 涉及的角色组件(标准)
- 基本实现 Demo(可以直接 copy 跑一下看效果)
- 自己动手实战
- 需求
- 参考答案
- 相关话题
- 参考文章
应用场景
- 需要给一个现有类添加附加功能,但由于某些原因不能使用继承来生成子类进行扩充时,可以使用装饰模式。
- 当对象的功能要求可以动态地添加,也可以再动态地撤销时,可以使用装饰模式。
涉及的角色和类(个人理解)
- 简单来说是两类角色:
Source(Component)
和Decorator
,即被装饰者(原类)
和装饰者
- 从类实现分析:
- 由于
被装饰者
和装饰者
需要实现同样的方法,需要定义一个抽象接口。 - 为便于区分,被装饰者抽象接口叫
Component
,具体的被装饰者叫ConcreteComponent
- 考虑到可能有多个具体的装饰器,需要一个抽象类装饰器叫
Decorator
,它的多个具体实现类分别叫AConcreteDecorator
,BConcreteDecorator
- 由于
涉及的角色组件(标准)
被装饰组件接口
:Component具体的被装饰组件实现类
:AConcreteComponent, BConcreteComponent装饰器抽象类
:Decorator具体的被装饰器实现类
:AConcreteDecorator, BConcreteDecorator
基本实现 Demo(可以直接 copy 跑一下看效果)
- Demo,有一个
图形Shape
被装饰接口,有两个被装饰者的具体实现 Circle, Rectangle
,有两个装饰器,分别用来给图形设置绿色
和给图形设置红色
- 在本地创建一个java类
DecoratorTest02
,然后 copy 一下代码,直接跑
/*** 装饰器模式要实现的类* Component* AConcreteComponent* BConcreteComponent* Decorator* AConcreteDecorator* BConcreteDecorator*/// 1. 实现 被装饰器组件 操作
// Component
interface Shape {void draw();
}// 2. 实现 被装饰器组件 的具体实现类
// AConcreteComponent
class Circle implements Shape {@Overridepublic void draw() {System.out.println("画一个圆形");}
}// BConcreteComponent
class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("画一个方形");}
}// 3. 实现 装饰器
// Decorator
abstract class Decorator implements Shape {// 使用 protected,便于子类访问protected Shape shape;public Decorator(Shape shape) {this.shape = shape;}@Overridepublic void draw() {shape.draw();}}// 4. 实现 具体功能的 装饰器
// AConcreteDecorator
class RedDecorator extends Decorator {public RedDecorator(Shape shape) {super(shape);}@Overridepublic void draw() {// 可以在原功能之前增加功能// 调用原方法shape.draw();// 可以在原功能之后增加功能setRed(shape);}// 装饰器功能:设置红色public void setRed(Shape shape) {System.out.println("设置红色");}
}// BConcreteDecorator
class GreenDecorator extends Decorator {public GreenDecorator(Shape shape) {super(shape);}@Overridepublic void draw() {shape.draw();setRed(shape);}// 装饰器功能:设置绿色public void setRed(Shape shape) {System.out.println("设置绿色");}
}// 5. 在客户端中使用 装饰器
public class DecoratorTest02 {public static void main(String[] args) {// 1. 标准的使用过程,画一个 圆,红色的// 创建一个 被装饰器组件圆Circle circle = new Circle();// 创建一个 具体的装饰器红色RedDecorator redDecorator = new RedDecorator(circle);// 执行方法redDecorator.draw();// 2. 画一个 方形,红色的new RedDecorator(new Rectangle()).draw();// 3. 画一个 方形,绿色的new GreenDecorator(new Rectangle()).draw();// 总结 可以看出,使用装饰器,可以对原来的类 动态添加、删除装饰功能}
}
自己动手实战
需求
小明喜欢品尝不同口味的咖啡,他发现每种咖啡都可以加入不同的调料,比如牛奶、糖和巧克力。他决定使用装饰者模式制作自己喜欢的咖啡。
请设计一个简单的咖啡制作系统,使用装饰者模式为咖啡添加不同的调料。系统支持两种咖啡类型:黑咖啡(Black Coffee)和拿铁(Latte)。
要求:可以制作 加牛奶的黑咖啡,加糖的黑咖啡,加糖的拿铁咖啡
原练习题链接
参考答案
// Component: 被装饰者接口
interface Coffee {void createCoffee();
}// AConcreteComponent: 被装饰者的具体实现类 黑咖啡
class BlackCoffee implements Coffee {@Overridepublic void createCoffee() {System.out.println("create black coffee");}
}// BConcreteComponent: 被装饰者的具体实现类 拿铁咖啡
class Latte implements Coffee {@Overridepublic void createCoffee() {System.out.println("create latte coffee");}
}// Decorator: 装饰器抽象类
abstract class Decorator implements Coffee {// 让子类可以访问到 被装饰者protected Coffee coffee;public Decorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic void createCoffee() {coffee.createCoffee();}
}// AConcreteDecorator: 装饰器具体实现类 加牛奶装饰
class MilkDecorator extends Decorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic void createCoffee() {// 在原方法之前 做装饰washCup();// 执行原方法coffee.createCoffee();// 在原方法之后做装饰addMilk(coffee);}// 装饰功能:洗杯子public void washCup() {System.out.println("洗杯子");}// 装饰功能:加牛奶public void addMilk(Coffee coffee) {System.out.println("加入牛奶");}
}// BConcreteDecorator: 装饰器具体实现类 加糖装饰
class SugarDecorator extends Decorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic void createCoffee() {coffee.createCoffee();addSugar(coffee);}public void addSugar(Coffee coffee) {System.out.println("加入一些糖");}
}public class DecoratorTest01 {public static void main(String[] args) {BlackCoffee blackCoffee = new BlackCoffee();SugarDecorator sugarDecorator = new SugarDecorator(blackCoffee);sugarDecorator.createCoffee();}
}
相关话题
- Java IO 流中如何应用的装饰器模式
- 什么时候可以考虑使用装饰器模式
- 能徒手写一个装饰器模式的demo吗
参考文章
- https://github.com/youngyangyang04/kama-DesignPattern/blob/main/DesignPattern/8-%E8%A3%85%E9%A5%B0%E6%A8%A1%E5%BC%8F.md
- https://www.runoob.com/design-pattern/decorator-pattern.html
- https://pdai.tech/md/java/io/java-io-basic-design-pattern.html
- https://kamacoder.com/problempage.php?pid=1086