装饰者设计模式简介
* 装饰者设计模式:在不改变原有对象功能代码的情况下,动态地给一个对象添加新功能。
* 一个抽象类,两个分支
* |——单点商品【组件】
* |——装饰类(持有被装饰对象的引用)装饰类和被装饰的类具有相同的父类
* 何时使用:在不想增加很多子类的情况下扩展类。
* 优点:装饰类和被装饰类可以独立发展,不会相互耦合,既是is a Component又有 has a Component
* 装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
* 缺点:多层装饰比较复杂。
* 使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。3、层级动态计算 4.形如 树形结构,层级结构,组织结构可考虑
* 注意事项:可代替继承。
* 应用举例:女孩化妆:其本质还是那个人,只不过化了妆。人--》超人,衣着搭配、饮料搭配,
层级目录结构
饮料抽象类【组件】
/**
* 饮料抽象类
*/
public abstract class Drink {
//饮料描述
private String description;
//价格 为了方便起见直接用String 实际项目价格要用BigDecimal
private String price;
public Drink() {
}
//子类构造函数初始化,super(description,price)
public Drink(String description, String price) {
this.description = description;
this.price = price;
}
//抽象计算方法
public abstract String cost();
//提供getter/setter 方便修改饮料价格
public String getDescription() {
return description +":¥"+this.price;
}
public void setDescription(String description) {
this.description = description;
}
//protected 让其他包中的子类可以使用
protected String getPrice() {
return price;
}
protected void setPrice(String price) {
this.price = price;
}
}
咖啡父类
/**
*
* 咖啡
*/
public class Coffee extends Drink {
public Coffee(){}
public Coffee(String description, String price){
super(description,price);
}
@Override
public String cost() {
return super.getPrice();
}
}
咖啡子类
/**
*
* 无咖啡因咖啡
*/
public class Decaf extends Coffee{
public Decaf(){}
public Decaf(String description,String price){
super(description,price);
}
}
/**
*
* 兑了热水的咖啡
*/
public class LongbBlack extends Coffee {
public LongbBlack(){}
public LongbBlack(String description, String price){
super(description,price);
}
}
/**
*
* 浓缩的咖啡
*/
public class ShortBlack extends Coffee {
public ShortBlack(){}
public ShortBlack(String description,String price){
super(description,price);
}
}
装饰父类
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
/**
*
* 装饰者设计模式:在不改变原有对象功能代码的情况下,动态地给一个对象添加新功能。
* 一个抽象类,两个分支
* |——单点商品【组件】
* |——装饰类(持有被装饰对象的引用)装饰类和被装饰的类具有相同的父类
* 何时使用:在不想增加很多子类的情况下扩展类。
* 优点:装饰类和被装饰类可以独立发展,不会相互耦合,既是is a Component又有 has a Component
* 装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
* 缺点:多层装饰比较复杂。
* 使用场景: 1、扩展一个类的功能。 2、动态增加功能,动态撤销。3、层级动态计算
* 注意事项:可代替继承。
* 应用举例:女孩化妆:其本质还是那个人,只不过化了妆。人--》超人,衣着搭配、饮料搭配
*/
public class Decorator extends Drink {
public Decorator() {
}
private Drink drink;
public Decorator(Drink drink) {
this.drink = drink;
}
/**
* 计算总花费
* @return
*/
@Override
public String cost() {
double result = new BigDecimal(super.getPrice()).add(new BigDecimal(drink.cost())).setScale(3, RoundingMode.HALF_UP).doubleValue();
DecimalFormat df=new DecimalFormat("0.00");
return df.format(result);
}
/**
* 展示购物清单
* @return
*/
@Override
public String getDescription() {
return drink.getDescription() + "\r\n" + super.getDescription();
}
}
装饰器子类
import design_pattern.decoration.Drink;
/**
*
* 巧克力装饰器
*/
public class ChocolateDecorator extends Decorator{
public ChocolateDecorator(Drink drink){
super(drink);
super.setDescription("加了巧克力");
super.setPrice("4");
}
}
import design_pattern.decoration.Drink;
/**
*
* 牛奶装饰器
*/
public class MilkDecorator extends Decorator{
public MilkDecorator(Drink drink){
super(drink);
super.setDescription("加了牛奶");
super.setPrice("10");
}
}
咖啡吧
import design_pattern.decoration.coffee.Coffee;
import design_pattern.decoration.coffee.Decaf;
import design_pattern.decoration.decorator.ChocolateDecorator;
import design_pattern.decoration.decorator.MilkDecorator;
/**
*
* 咖啡馆测试
*/
public class CoffeeBar {
public static void main(String[] args) {
Coffee coffee=new Decaf("无咖啡因咖啡","20");
System.out.println("coffee.getDescription() = " + coffee.getDescription());
System.out.println("coffee.getPrice() = " + coffee.cost());
System.out.println("--------加巧克力的无咖啡因咖啡--------华丽的分割线------------");
ChocolateDecorator chocolateDecorator = new ChocolateDecorator(coffee);
System.out.println(chocolateDecorator.getDescription());
System.out.println(chocolateDecorator.cost());
System.out.println("---------又加牛奶又加巧克力的无咖啡因咖啡-------华丽的分割线------------");
MilkDecorator milkDecorator=new MilkDecorator(chocolateDecorator);
System.out.println(milkDecorator.getDescription());
System.out.println(milkDecorator.cost());
}
}
核心代码逻辑
在Decorator的getCost()方法,使用的是当前的价格+多态所指向的实际Drink实例【可能是coffee,也可能是decorator】的总花费。
由于coffee和decorator都是drink的子类,所以无论具体实例是谁,都形成了递归调用
执行结果
写在最后
学到了就要教人,赚到了就要给人!
The more I think, the luckier I am.
【越思考,越幸运】