(1)概述
在不改变现有对象结构的情况下,动态的给该对象增加额外的职责或功能
(2)结构
- 抽象构建角色:定义一个抽象接口以规范准备接收附加责任的对象
- 具体构建角色:实现抽象构建,通过装饰角色为其添加一些职责
- 抽象装饰角色:继承或实现抽象构建,并包含具体构建的实例,可以通过其子类扩展具体构建的功能
- 具体装饰角色:实现抽象装饰的相关方法,并给具体构建对象添加附加的职责或功能
(3)案例
以快餐店为例:
抽象构建角色
public abstract class FastFood {
private float price;
private String desc;
public FastFood() {
}
public FastFood(float price, String desc) {
this.price = price;
this.desc = desc;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
/**
* 计算价格
*
* @return
*/
public abstract float cost();
}
具体构建角色
public class FriedNoodles extends FastFood {
public FriedNoodles() {
super(8, "炒面");
}
@Override
public float cost() {
return super.getPrice();
}
}
public class FriedRice extends FastFood {
public FriedRice() {
super(10, "炒饭");
}
@Override
public float cost() {
return super.getPrice();
}
}
抽象装饰角色
public abstract class Garnish extends FastFood {
private FastFood fastFood;
public Garnish(FastFood fastFood, float price, String desc) {
super(price, desc);
this.fastFood = fastFood;
}
public FastFood getFastFood() {
return fastFood;
}
public void setFastFood(FastFood fastFood) {
this.fastFood = fastFood;
}
}
具体装饰角色
public class Egg extends Garnish {
public Egg(FastFood fastFood) {
super(fastFood, 1, "鸡蛋");
}
@Override
public float cost() {
//价格:鸡蛋 + 快餐的价格
return super.getPrice() + super.getFastFood().cost();
}
@Override
public String getDesc() {
//描述:鸡蛋 + 具体的快餐
return super.getDesc() + super.getFastFood().getDesc();
}
}
public class Bacon extends Garnish {
public Bacon(FastFood fastFood) {
super(fastFood, 2, "培根");
}
@Override
public float cost() {
//价格:培根 + 快餐的价格
return super.getPrice() + super.getFastFood().cost();
}
@Override
public String getDesc() {
//描述:培根 + 具体的快餐
return super.getDesc() + super.getFastFood().getDesc();
}
}
测试
public class Client {
public static void main(String[] args) {
//炒饭
FastFood food = new FriedRice();
System.out.println(food.getDesc() + " " + food.cost() + "元");
//再加一个鸡蛋
food = new Egg(food);
//System.out.println(food.getDesc() + " " + food.cost() + "元");
//加培根
food = new Bacon(food);
System.out.println(food.getDesc() + " " + food.cost() + "元");
}
}
(4)优缺点
- 装饰者模式可以带来比继承更加灵活的扩展功能,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结果
- 遵循开闭原则,继承是静态的附加责任,装饰者则是动态的附加责任
- 装饰类和被装饰类可以各自独立发展,不会产生耦合,装饰者模式是继承的一个替代模式,可以动态扩展一个实现类的功能
(5)使用场景
当不能采用继承的方式对系统进行扩充或采用继承不利于系统扩展和维护时
- 类中存在大量独立的扩展,使用继承可能会造成类爆炸时
- 被
final
修饰的类
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加功能或职责
- 当对象的功能要求动态添加,动态移除时
(6)静态代理与装饰者模式的区别
相同点:
- 都要实现与目标类相同的业务接口
- 在两个类中都要声明目标对象
- 都可以在不修改目标对象的前提下进行功能增强
不同点:
目的不同:
装饰者增强目标对象
静态代理保护和隐藏目标对象
获取目标对象构建的地方不同
装饰者中的目标对象由外界传递(通过构造方法或set赋值)
静态代理的目标对象在代理类内部创建,以此来完成隐藏和保护
评论 (0)