装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法完整性的前提下,提供了额外的功能。
何时使用::一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下扩展类。
如何解决:将具体功能职责划分,同时继承装饰者模式。
关键代码: 使用组合关系来创建一个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰器模式的目标。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂。
代码案例
构建抽象角色:
/**
* @className: Drink
* @description:
* @author: charon
* @create: 2022-03-19 22:48
*/
public abstract class Drink {
/**
* 描述
*/
public String desc;
/**
* 价格
*/
private float price = 0.0f;
/**
* Gets the value of desc
*
* @return the value of desc
*/
public String getDesc() {
return desc;
}
/**
* Sets the desc
*
* @param desc desc
*/
public void setDesc(String desc) {
this.desc = desc;
}
/**
* Gets the value of price
*
* @return the value of price
*/
public float getPrice() {
return price;
}
/**
* Sets the price
*
* @param price price
*/
public void setPrice(float price) {
this.price = price;
}
/**
* 计算费用的方法,交给子类实现
* @return
*/
public abstract float cost();
}
构建具体角色:
package com.charon.decorator;
/**
* @className: Coffee
* @description:
* @author: charon
* @create: 2022-03-19 22:37
*/
public class Coffee extends Drink{
@Override
public float cost() {
return super.getPrice();
}
}
package com.charon.decorator;
/**
* @className: LongBlack
* @description:
* @author: charon
* @create: 2022-03-19 23:16
*/
public class LongBlack extends Coffee{
public LongBlack() {
setDesc(" 美式咖啡 ");
setPrice(5.0f);
}
}
package com.charon.decorator;
/**
* @className: Decaf
* @description:
* @author: charon
* @create: 2022-03-19 23:11
*/
public class Decaf extends Coffee{
public Decaf() {
setDesc(" 无因咖啡 ");
setPrice(1.0f);
}
}
抽象装饰角色:
package com.charon.decorator;
/**
* @className: Decorator
* @description:
* @author: charon
* @create: 2022-03-19 23:13
*/
public class Decorator extends Drink{
/**
* 使用聚合的方式
*/
private Drink drink;
public Decorator(Drink drink) {
this.drink = drink;
}
@Override
public float cost() {
return super.getPrice() + drink.cost();
}
@Override
public String getDesc() {
return super.getDesc() + "&&" + drink.getDesc();
}
}
具体装饰角色:
package com.charon.decorator;
/**
* @className: Milk
* @description:
* @author: charon
* @create: 2022-03-19 23:17
*/
public class Milk extends Decorator{
public Milk(Drink drink) {
super(drink);
setDesc(" 牛奶 ");
setPrice(2.0f);
}
}
package com.charon.decorator;
/**
* @className: Soy
* @description:
* @author: charon
* @create: 2022-03-19 23:18
*/
public class Soy extends Decorator{
public Soy(Drink drink) {
super(drink);
setDesc(" 豆浆 ");
setPrice(1.5f);
}
}
测试
package com.charon.decorator;
/**
* @className: Client
* @description:
* @author: charon
* @create: 2022-03-19 23:19
*/
public class Client {
public static void main(String[] args) {
// 点一份美式咖啡
Drink longBlack = new LongBlack();
System.out.println(longBlack.getDesc() + " 费用: " + longBlack.cost());
// 添加一点牛奶
longBlack = new Milk(longBlack);
System.out.println(" 添加了:" + longBlack.getDesc() + " 费用:" + longBlack.cost());
// 再添加一点豆浆
longBlack = new Soy(longBlack);
System.out.println(" 添加了:" + longBlack.getDesc() + " 费用:" + longBlack.cost());
}
}
运行结果
美式咖啡 费用: 5.0
添加了: 牛奶 && 美式咖啡 费用:7.0
添加了: 豆浆 && 牛奶 && 美式咖啡 费用:8.5