装饰着模式

装饰者模式

设计模式类型 : 结构性

概念 : 不改变原有类的对象 , 动态地将额外的功能附加到该对象上 ;

扩展对象功能 : 这种功能扩展方式比类继承更加灵活 ;

装饰者模式 : 移除类中的被装饰功能 , 将被装饰类简化 , 区分类的核心职责和装饰功能 ;

装饰者模式适用场景 :

① 功能扩展 : 为一个类扩展功能 , 为其添加额外的职责 ( 强调扩展 )

② 动态添加撤销功能 : 为一个对象动态添加额外功能 , 同时这些被添加的功能还能被动态撤销 ( 强调动态 )

**装饰者模式四个相关类 **

抽象构件类 : 这是核心 , 后面的三个类都需要继承该类

具体构件类 : 定义装饰者模式时用不到 , 在客户端被用户调用时 , 才初始化

抽象装饰者类 : 所有装饰者类的父类 , 需要继承抽象的被装饰者类,其持有一个构件类的实例

具体装饰者类 : 继承抽象的装饰者类 , 通过构造函数传入实体的构建类 , 其实现的抽象装饰者方法中 , 需要调用传入的实体对象的对应方法 , 然后加入额外的操作

image-20231228202730469

例子

抽象构件类

1
2
3
4
5
6
7
8
public abstract class Beverage {
String description ="Unknown Beverage";
double cost;
public String getDescription(){
return description;
}
public double getCost() { return cost;}
}

具体构件类

1
2
3
4
5
6
7
8
9
10
public class DarkRoast extends Beverage{
public DarkRoast(){
description = "DarkRoast";
cost = 1.05;
}
@Override
public double getCost() {
return cost;
}
}
1
2
3
4
5
6
7
8
9
10
public class Espresso extends Beverage{
public Espresso(){
description = "Espresso";
cost = 1.99;
}
@Override
public double getCost() {
return cost;
}
}
1
2
3
4
5
6
7
8
9
10
public class HouseBlend extends Beverage{
public HouseBlend(){
description = "House Blend Coffee";
cost = 0.89;
}
@Override
public double getCost() {
return cost;
}
}

抽象装饰者类

1
2
3
4
5
6
7
8
public abstract class CondimentDecorator extends Beverage {
Beverage beverage;
public CondimentDecorator(Beverage beverage){
this.beverage = beverage;
}
public abstract String getDescription();
public abstract double getCost();
}

具体装饰者类

1
2
3
4
5
6
7
8
9
10
11
12
public class Mocha extends CondimentDecorator{
public Mocha(Beverage beverage){
super(beverage);
}
public String getDescription(){
return beverage.getDescription() + ", Mocha";
}
@Override
public double getCost() {
return 0.2 + beverage.getCost();
}
}
1
2
3
4
5
6
7
8
9
10
11
public class Soy extends CondimentDecorator{
public Soy(Beverage beverage) {
super(beverage);
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double getCost() {
return 0.15 + beverage.getCost();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class Whip extends CondimentDecorator {
public Whip(Beverage beverage) {
super(beverage);
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double getCost() {
return 0.10 + beverage.getCost();
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class StarbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new Espresso(); //订一杯浓缩咖啡,不加料
System.out.println(beverage.getDescription()+" $"+beverage.getCost());

Beverage beverage1 = new DarkRoast(); //订一杯深培咖啡
beverage1 = new Mocha(beverage1); //加摩卡
beverage1 = new Soy(beverage1); //加豆浆
System.out.println(beverage1.getDescription()+" $"+beverage1.getCost());

Beverage beverage2 = new HouseBlend(); //订一杯首选咖啡
beverage2 = new Whip(beverage2); //加奶泡
beverage2 = new Whip(beverage2); //加奶泡
//双倍奶泡
System.out.println(beverage2.getDescription()+" $"+beverage2.getCost());
}
}

image-20231228201940142

**装饰者模式优点 **

① 扩展灵活 : 使用装饰者模式 , 比继承更加灵活 ; 使用装饰者模式扩展类功能 , 不会改变原来的类

② 排列组合 : 对装饰类进行各种排列组合 , 可实现不同的扩展功能

③ 开闭原则 : 装饰者模式符合开闭原则 , 被装饰的类 , 和装饰类相互独立 , 互不干扰

**装饰者模式缺点 **

① 程序复杂 : 需要编写更多的代码 , 生成更多的类 , 程序的复杂性增加了

② 动态 / 多层 装饰 : 动态 / 多层 装饰一个类时 , 程序更复杂

**继承与装饰者模式对比 **

① 继承复杂 : 使用继承扩展功能 , 需要生成很多子类 , 系统复杂性增加

② 继承静态 : 继承在编译时就要确定扩展的功能 , 是静态的

③ 装饰者模式动态扩展 : 装饰者模式可以动态扩展功能 , 可以在代码运行时扩展功能

**装饰者模式与代理模式 **

① 注重点 : 装饰者模式注重动态扩展功能 ; 代理模式注重对对象访问的控制 , 代理类对用户隐藏具体细节

② 实例对象的使用 : 装饰者模式将原始对象作为参数传递给装饰者类构造器 ; 代理模式中在代理类中创建实例对象

装饰者模式与适配器模式 : 二者都是包装模式

① 装饰者模式 : 装饰者模式中 , 装饰者和被装饰者实现相同的接口 , 或装饰者是被装饰者的子类 ;

② 适配器模式 : 适配器模式中 , 适配器和被适配的类有不同的接口 , 可能有部分接口重合 ;


装饰着模式
http://example.com/2023/10/15/计算机基础/设计模式/08-装饰者模式/
作者
PALE13
发布于
2023年10月15日
许可协议