装饰者模式
定义
指在不改变原有对象结构下,动态的给对象增加一些额外的功能的模式。
理解
比如再快餐店吃饭,在店里可以吃炒饭、粉面。如果吃炒饭可以加配料(火腿、鸡蛋、白菜、饮料等),如果吃粉面也是可以加以上的配料,不同的配料不同的价格,最后计算共花费多少钱
角色
- 抽象构件角色:定义一个抽象接口规范,准备接口附加责任的对象(抽象类)
- 具体构件角色:实现抽象构件,通过装饰角色为其添加主要职责(比如主食炒饭、粉面)
- 抽象装饰角色:继承或者实现抽象构件,并包含具体构件对象,可以通过其子类扩展具体构件的功能
- 具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任(比如配料)
适用场景
- 当不能采用继承的方式对系统扩充或者采用继承的方式不利于系统的扩展和维护时
- 在不影响其他对象的情况下,动态的添加职责和撤销功能
案例实现
以快餐店点餐为例:
1.快餐店—抽象构件角色
public abstract class FastFood {
private float price;//价格,比如炒饭10块,粉面5块等
private String desc;//餐类型名,比如炒饭,粉面
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;
}
//计算费用
protected abstract float cost();
}
2.炒饭类—具体构件角色
public class FriedRice extends FastFood{
public FriedRice() {
super(10,"炒饭");
}
@Override
protected float cost() {
return getPrice();
}
}
//...可以有多个具体构件角色,这里仅写一个举例
3.抽象装饰角色
//继承抽象构件并包含具体构件的引用
public abstract class Garnish extends FastFood{
private FastFood fastFood;//具体构件的顶层引用
public FastFood getFastFood() {
return fastFood;
}
public void setFastFood(FastFood fastFood) {
this.fastFood = fastFood;
}
public Garnish(FastFood fastFood, float price, String desc) {
super(price, desc);
this.fastFood = fastFood;
}
}
4.配料类(鸡蛋)–具体装饰者
public class Egg extends Garnish{
public Egg(FastFood fastFood) {
super(fastFood,1,"+鸡蛋");
}
@Override
protected float cost() {//总价格,前面getPrice是鸡蛋价格,后面getFastFood().cost()是炒饭价格
return getPrice()+ getFastFood().cost();
}
@Override
public String getDesc() {
return getFastFood().getDesc()+super.getDesc();
}
}
5.测试类
public class ClientTest {
public static void main(String[] args) {
FastFood food = new FriedRice();//10块钱炒饭
food = new Egg(food);//鸡蛋+1
food = new Egg(food);//鸡蛋+1
food = new Egg(food);//鸡蛋+1
System.out.println(food.getDesc()+" "+food.cost());//炒饭+鸡蛋+鸡蛋+鸡蛋 13.0
}
}