引入问题
咖啡馆订单系统项目
咖啡种类+调料
设计目标 扩展性好 改动方便 维护方便
1.继承方法做类会很多
2.超类 每种调料设置boolean变量 加调料 不友好
3.装饰者模式
不变和变 梳理出来
一个是主体
一个是装饰者
运行过程中 添加新的功能
形象:就是快递
超类
单品咖啡
调料
装饰者模式就像打包一个快递
1 主题:手机
2.包装:盒子装起来
装饰者模式:动态的将新功能附件到对象上 在对象功能扩展方面,它比继承更有弹性
适用场景
适用场景:
1.继承关系不利于系统维护,甚至不能使用继承关系的场景。比如,当继承导致类爆炸时、目标类被 final 修饰时,都不宜通过创建目标类的子类来扩展功能。
2.要求不影响其他对象,为特定目标对象添加功能。
3.要求动态添加、撤销对象的功能。
代码
核心:
1.装饰者模式的核心思想是通过创建一个装饰对象(即装饰者),动态扩展目标对象的功能,并且不会改变目标对象的结构,提供了一种比继承更灵活的替代方案。
2.需要注意的是,装饰对象要与目标对象实现相同的接口,或继承相同的抽象类;
3.装饰对象需要持有目标对象的引用作为成员变量,而具体的赋能任务往往通过带参构造方法来完成。
UML类图:
代码:
package com.decorator.day03.mode.mark;
public abstract class Beverage {
public String description="Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
package com.decorator.day03.mode.mark;
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
package com.decorator.day03.mode.mark;
//焦炒咖啡
public class DarkRoast extends Beverage {
public DarkRoast() {
description = "DarkRoast";
}
public double cost(){
return 1.1;
}
}
package com.decorator.day03.mode.mark;
//低咖
public class Decaf extends Beverage {
public Decaf() {
description = "Decaf";
}
public double cost(){
return 1.2;
}
}
package com.decorator.day03.mode.mark;
//蒸馏咖啡
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost(){
return 1.99;
}
}
package com.decorator.day03.mode.mark;
//首选咖啡
public class HouseBlend extends Beverage{
public HouseBlend(){
description="House Blend Coffee";
}
public double cost(){
return 8.9;
}
}
package com.decorator.day03.mode.mark;
public class Mocha extends CondimentDecorator{
Beverage beverage;
public Mocha(Beverage beverage){
this.beverage=beverage;
}
public String getDescription(){
return beverage.getDescription()+",Mocha";
}
public double cost(){
return 1.0+ beverage.cost();
}
}
package com.decorator.day03.mode.mark;
public class Soy extends CondimentDecorator{
Beverage beverage;
public Soy(Beverage beverage){
this.beverage=beverage;
}
public String getDescription(){
return beverage.getDescription()+",Soy";
}
public double cost(){
return 2.0+ beverage.cost();
}
}
package com.decorator.day03.mode.mark;
public class Whip extends CondimentDecorator{
Beverage beverage;
public Whip(Beverage beverage){
this.beverage=beverage;
}
public String getDescription(){
return beverage.getDescription()+",Whip";
}
public double cost(){
return 1.5+ beverage.cost();
}
}
package com.decorator.day03.mode.mark;
public class StarbuzzCoffee {
public static void main(String[] args) {
Beverage beverageE=new Espresso();
System.out.println(beverageE.getDescription()+" $" +beverageE.cost());
Beverage beverageD=new DarkRoast();
beverageD=new Mocha(beverageD);
beverageD=new Mocha(beverageD);
beverageD=new Whip(beverageD);
System.out.println(beverageD.getDescription()+" $" +beverageD.cost());
}
}
代码分析
1.都继承Beverage
2.装饰者的实现类的构造方法中 持有目标类的父类引用
3. Beverage beverageD=new DarkRoast();
beverageD=new Mocha(beverageD);
beverageD=new Mocha(beverageD);
beverageD=new Whip(beverageD);
调用是从最外层的方法,向最内层调用
比如cost方法
1.5+ beverage.cost()
1.5+ 1.0+ beverage.cost()
1.5+ 1.0+1.0+ beverage.cost()
1.5+ 1.0+1.0+1.1
Java内置装饰者模式 设计IO
FilterInputStream 就是一个装饰者类
开放-关闭原则的设计意义 (类应该对扩展开放,对修改关闭)
新调料添加 开放
对原有的调料修改是关闭
部分参考:
https://www.zhihu.com/question/32007641/answer/2750755082