课堂笔记
装饰模式概述
动态的给一个对象增加一些额外的职责
装饰模式结构
1.Component(抽象构件)
它是具体构件和抽象装饰类的共同父类。声明了一种业务,该业务在具体构件里面实现。
2.ConcreteComponent(具体构件)
它是抽象构件的子类,实现了抽象构件中声明的方法,且抽象装饰类可以给他增加额外的职责。
3.Decorator(抽象装饰类)
它也是抽象构件的子类,用于给具体构件增加额外的方法,但只是声明,具体的实现交给具体装饰类。它维护了一个指向抽象构件对象的引用,通过这个引用调用装饰之前的业务,并通过子类实现扩展,达到装饰的目的。
4.ConcreteDecorator(具体装饰类)
它是抽象装饰类的子类, 实现抽象装饰类中的方法,给具体构件添加新的业务。
装饰模式实例(作业)
某咖啡店为了满足顾客的口味,允许顾客可以在普通咖啡Coffee (5.00元)中自由地加入多种配料(糖Sugar 1.50元、奶Milch 1.00元、冰Ice 0.50元等)。给咖啡店设计一个咖啡计价(calcAmount(): BigDecimal)软件,该软件要遵守面向对象设计原则,咖啡的价格随着加入的配料而变化,并满足咖啡店后期可能还会增加新配料(如巧克力Chocolate等)和咖啡品种的需求。注意金额精度问题!
设计类图
Component(抽象构件)
import java.math.BigDecimal;
public abstract class Component {
public abstract BigDecimal calcAmount();
}
Coffee(具体结构)
import java.math.BigDecimal;
public class Coffee extends Component{
@Override
public BigDecimal calcAmount() {
return new BigDecimal("5.00");
}
}
Decorator(抽象装饰类)
import java.math.BigDecimal;
public class Decorator extends Component{
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public BigDecimal calcAmount() {
return component.calcAmount();
}
}
Suger、Ice、Milk(具体装饰类)
import java.math.BigDecimal;
public class Suger extends Decorator{
static private double price=1.50;
public Suger(Component component) {
super(component);
}
@Override
public BigDecimal calcAmount() {
BigDecimal bigDecimal=new BigDecimal(addsuger());
return super.calcAmount().add(bigDecimal);
}
public String addsuger(){
return "1.50";
}
}
public class Milk extends Decorator{
public Milk(Component component) {
super(component);
}
@Override
public BigDecimal calcAmount() {
BigDecimal bigDecimal=new BigDecimal(addmike());
return super.calcAmount().add(bigDecimal);
}
public String addmike(){
return "1.00";
}
}
public class Ice extends Decorator {
public Ice(Component component) {
super(component);
}
@Override
public BigDecimal calcAmount() {
BigDecimal bigDecimal=new BigDecimal(addice());//把加冰转换为BigDecimal
return super.calcAmount().add(bigDecimal);
}//
public String addice(){
return "0.50";
}
}
透明装饰模式与半透明装饰模式
透明装饰模式
无论是创建具体构件对象,还是具体装饰对象。我们统一使用Component(抽象构件)来声明这些对象。这一特点使得,透明装饰模式可以对同一个对象,装饰多次。
client代码
import java.math.BigDecimal;
public class client {
public static void main(String[] args) {
Component componentone=new Coffee();//父类使用子类的构造函数,用多态calcAmount()更新自己的方法。
Component componentone1=new Suger(componentone);
Component componentone2=new Milk(componentone1);
Component componentone3=new Milk(componentone2);
BigDecimal sum=componentone3.calcAmount();//记录顾客最终付费的coffee价格
System.out.println("顾客一花费:"+sum);//顾客一
Component componenttwo=new Coffee();//父类使用子类的构造函数,用多态calcAmount()更新自己的方法。
Component componenttwo1=new Suger(componenttwo);
Component componenttwo2=new Ice(componenttwo1);
Component componenttwo3=new Milk(componenttwo2);
BigDecimal sum2=componenttwo3.calcAmount();//记录顾客最终付费的coffee价格
System.out.println("顾客二花费:"+sum2);//顾客二
}
}
坏处是具体装饰类(Ice,Suger,Milk)里面扩展的方法,没法使用,只能用Component里面有的方法。
半透明装饰模式
为了用具体装饰类里面的方法,一部分用Ice,Suger,Milk声明这些对象
client代码
import java.math.BigDecimal;
public class client1 {
public static void main(String[] args) {
Component component=new Coffee();
Ice ice=new Ice(component);
BigDecimal sum=ice.calcAmount().add(new BigDecimal(ice.addice()));
System.out.println(sum);
}
}
这个相当于加了两遍冰。