装饰模式
1.概念
动态地为对象附加上额外的职责
其目的是包装一个对象,从而可以在运行时动态添加新的职责。每个装饰器都可以包装另一个装饰器,这样理论上来说可以对目标对象进行无限次的装饰。
2.装饰器类图
3.代码
一个早餐店经营两种主食:汉堡和吐司,一段时间后需要加个配料。
主要思路是:以主食(汉堡、吐司)为主体,然后再运行时以配料(火腿、起司)装饰为主食。其UML图为:
(1)抽象构建类————Breakfast.java,早餐的抽象父类
public abstract class Breakfast {
public String description="未知";
public String getDescription(){
return description;
}
public abstract Double cost();
}
(2)抽象装饰类————CondimentDecorator.java,是早餐抽象类的子类
public abstract class CondimentDecorator extends Breakfast{
Breakfast myfood;
public CondimentDecorator(Breakfast myfood){
this.myfood=myfood;
}
@Override
public String getDescription(){
return myfood.getDescription();
}
@Override
public Double cost(){
return myfood.cost();
}
}
(3)具体构建类————Toast.java、Burger.java
Toast.java
public class Toast extends Breakfast {
public Toast(){
description="吐司";
}
public Double cost(){
return 10d;
}
}
Burger.java
public class Burger extends Breakfast {
public Burger(){
description="汉堡";
}
@Override
public Double cost(){
return 15d;
}
}
(4)具体装饰类————Cheese.java、Ham.java
Cheese.java
public class Cheese extends CondimentDecorator {
public Cheese(Breakfast myfood) {
super(myfood);
}
@Override
public Double cost() {
return super.cost() + 5;
}
@Override
public String getDescription() {
return super.getDescription() + ",起司";
}
}
Ham.java
public class Ham extends CondimentDecorator {
public Ham(Breakfast myfood) {
super(myfood);
}
@Override
public Double cost() {
return super.cost() + 10;
}
@Override
public String getDescription() {
return super.getDescription() + ",火腿";
}
}
(5)客户端测试类
public class Decorator {
public static void main(String args[]) {
Breakfast breakfast1 = new Toast();
System.out.println("您点的餐点为:" + breakfast1.getDescription() + "。价格为:" + breakfast1.cost());
Breakfast breakfast2 = new Toast();
breakfast2 = new Ham(breakfast2);
breakfast2 = new Ham(breakfast2);
System.out.println("您点的餐点为:" + breakfast2.getDescription() + "。价格为:" + breakfast2.cost());
Breakfast breakfast3 = new Burger();
breakfast3 = new Ham(breakfast3);
breakfast3 = new Cheese(breakfast3);
breakfast3 = new Cheese(breakfast3);
System.out.println("您点的餐点为:" + breakfast3.getDescription() + "。价格为:" + breakfast3.cost());
}
}
结果
您点的餐点为:吐司。价格为:10.0
您点的餐点为:吐司,火腿,火腿。价格为:30.0
您点的餐点为:汉堡,火腿,起司,起司。价格为:35.0
详细见:Java设计模式