目录
1、什么是装饰器模式
2、装饰器模式结构
3、具体实现
3.1 案例
3.2 代码实现
4、使用场景
定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
装饰(Decorator)模式中的角色:
我们先来看以下这个例子:平时我们都肯定吃过快餐,快餐肯定包含了炒饭、炒面等等,有时候“生活富裕”的时候,我们还会加个蛋再来根肠。
那么,如果我们此时想用代码的方式来实现,那肯定最容易想到以下方法:
①定义快餐类。
②定义炒饭类、炒面类来继承快餐类。
③定义蛋炒饭、蛋炒面、火腿肠炒饭、火腿肠炒面、火腿肠蛋炒饭、火腿肠蛋炒面。
显然,这种方式很容易想,不难理解,但是大家也很容易发现一个很严重的问题:“类爆炸”。即我们仅仅是举了炒饭、炒面,配料能加蛋和火腿的例子,就需要上面这么多类。可是正常的快餐店,还有炒河粉、饺子.......配料还有培根、鸡腿、鸭腿......
所以上述这种方式虽然能够实现,但是我们极力反对使用这种方式!不仅难用,而且违反了我们软件设计原则中的“合成复用原则”。因此,这个时候我们就需要使用“装饰者模式”来解决我们遇到的问题了。
以下代码实现依据上述例子来进行实现。(代码有点长,但是很简单的逻辑,大家细心看)
快餐类(抽象构件角色):
public abstract class FastFood { //快餐类
private String description;//描述
private int price;//价格
public abstract int cost(); //返回需要多少钱
public abstract String Description();//返回当前快餐描述
public FastFood(String description,int price){
this.description=description;
this.price=price;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
}
炒面类(具体构建角色):
public class FriedNoodle extends FastFood{ //炒面类
public FriedNoodle(String description, int price) {
super(description, price);
}
@Override
public int cost() {
return getPrice();
}
@Override
public String Description() {
return getDescription();
}
}
炒饭类(具体构建角色):
public class FriedRice extends FastFood{//炒饭类
public FriedRice(String description, int price) {
super(description, price);
}
@Override
public int cost() {
return getPrice();
}
@Override
public String Description() {
return getDescription();
}
}
配料类(抽象装饰角色):
public class SideDish extends FastFood{ //配菜类
private FastFood fastFood;
public SideDish(FastFood fastFood,String description, int price) {
super(description, price);
this.fastFood=fastFood;
}
@Override
public int cost() {
//价格应该是加配料前的食物价格+配料价格
return fastFood.cost()+getPrice();
}
@Override
public String Description() {
return fastFood.Description()+getDescription();
}
}
蛋类(具体装饰角色):
public class Egg extends SideDish {
public Egg(FastFood fastFood, String description, int price) {
super(fastFood, description, price);
}
}
火腿肠类(具体装饰角色):
public class Ham extends SideDish {
public Ham(FastFood fastFood, String description, int price) {
super(fastFood, description, price);
}
}
测试类:
public class Test {
public static void main(String[] args) {
FastFood friedRice = new FriedRice("炒饭", 10);//一开始点了一碗炒饭
FastFood egg = new Egg(friedRice, "加蛋", 1);//加个蛋
System.out.println("价格为:"+egg.cost());
System.out.println("描述为:"+egg.Description());
System.out.println("--------分界线--------");
Ham ham = new Ham(egg, "加肠", 2);//加个肠
System.out.println("价格为:"+ham.cost());
System.out.println("描述为:"+ham.Description());
}
}
运行结果:
可见,我们通过上述代码,完成了我们的案例,当然如果此时我们配菜多了一个“培根类”,那也仅需再创建一个“培根类”继承“配菜类”即可。
希望大家能耐心看完上述案例和代码,充分理解装饰器模式的好处。
①当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:
②在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
③当对象的功能要求可以动态地添加,也可以再动态地撤销时。