目录
前言:
上班族大多都有睡懒觉的习惯,每天早上上班时间都很紧张,于是很多人为了多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等,都是装饰器模式。
在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰器模式来实现。
定义与特点:
装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
特点:
-
装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
-
通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
-
装饰器模式完全遵守开闭原则
其主要缺点是:装饰器模式会增加许多子类,过度使用会增加程序得复杂性。
结构与实现:
模式的结构
装饰器模式主要包含以下角色。
-
抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
-
具体构件(ConcreteComponent)角色:实现抽象构件,通过装饰角色为其添加一些职责。
-
抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
-
具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
举例:
结构图:
代码实现:
//抽象构建角色
public abstract class Drink {
//描述
public String des;
//价格
private float price = 0.0f;//?
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
//计算费用的抽象方法
public abstract float cost();
}
//抽象装饰角色
public class Decorator extends Drink {
//被装饰者
private Drink obj;
//接收被装饰者
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public float cost() {
//自己的价格加上被装饰者的价格
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
//自己的描述+自己的价格+"&&"+被装饰者的描述
return super.getDes() + " " + super.getPrice() + " $$ " + obj.getDes();
}
}
//具体构建角色
public class LongBlack extends Drink{
public LongBlack(){
setDes("澳氏黑咖啡");
setPrice(5.0f);
}
@Override
public float cost() {
return super.getPrice();
}
}
//具体装饰角色
public class Chocolate extends Decorator{
public Chocolate(Drink obj) {
super(obj);
setDes("巧克力");
setPrice(3.0f);
}
}
//具体装饰角色
public class Milk extends Decorator{
public Milk(Drink obj) {
super(obj);
setDes("牛奶");
setPrice(2.0f);
}
}
测试:
结构图:
//测试类
public class Test {
public static void main(String[] args) {
//点一份澳氏黑咖啡
Drink order = new LongBlack();
System.out.println("费用= " + order.cost());
System.out.println("描述= " + order.getDes());
//加一份牛奶
order = new Milk(order);
System.out.println("order加了一份牛奶 费用= " + order.cost());
System.out.println("order加了一份牛奶 描述= " + order.getDes());
//加一份巧克力
order = new Chocolate(order);
System.out.println("order加了一份巧克力 费用= " + order.cost());
System.out.println("order加了一份巧克力 描述= " + order.getDes());
//加一份巧克力
order = new Chocolate(order);
System.out.println("order加了一份巧克力 费用= " + order.cost());
System.out.println("order加了一份巧克力 描述= " + order.getDes());
}
}
运行结果:
费用= 5.0
描述= 澳氏黑咖啡
order加了一份牛奶 费用= 7.0
order加了一份牛奶 描述= 牛奶 2.0 $$ 澳氏黑咖啡
order加了一份巧克力 费用= 10.0
order加了一份巧克力 描述= 巧克力 3.0 $$ 牛奶 2.0 $$ 澳氏黑咖啡
order加了一份巧克力 费用= 13.0
order加了一份巧克力 描述= 巧克力 3.0 $$ 巧克力 3.0 $$ 牛奶 2.0 $$ 澳氏黑咖啡