举个栗子:
老王是一个豆浆店的老板,因为豆浆品种多,生意火爆,我看着老王赚钱比较眼馋,晚上和他套近乎喝了点啤酒,老王就把配方分享给我了,具体配方如下:
如果此时由于生意火爆,老王又加了一种辅料:西瓜
类似于在开发中子类与父类的关系,子类功能比父类强大,但是由于子类数量增加,会形成类爆炸现象
如果实现子类继承父类,那么我们要写很多子类,这样做无疑增加了程序的臃肿性,并不是很灵活,这时,装饰者模式就可以帮助我们使得程序变得更简洁
装饰者模式又名包装模式,动态的给一个对象添加一些额外的职责,就扩展功能而言,它比生成子类的方式更加灵活
适用场景:
抽象组件(Component):给出一个抽象接口,以规范准备接受附加责任的对象
被装饰者(ConcreteComponent):Component的具体实现,也就是我们要装饰的具体的对象
装饰者组件(Decorator):持有组件(Component)对象的实例引用,该类的职责就是为了 装饰具体组件的对象,定义的基类
具体装饰(ConcreteDecorator):负责给构件对象装饰附加的功能
迁移到豆浆案例则具体职责如下:
package cn.homyit.designpattern.decorator;
/**
* Component
* 抽象组件
* 饮品接口
*/
public interface Drink {
//价格
double price();
//品种描述
String description();
}
package cn.homyit.designpattern.decorator;
/**
* ConcreteComponent
* 被装饰者
* 豆浆
*/
public class Soya implements Drink{
@Override
public double price() {
return 5;
}
@Override
public String description() {
return "纯豆浆";
}
}
package cn.homyit.designpattern.decorator;
/**
* Decorator
* 装饰器组件
* 1.抽象类
* 2.实现抽象组件接口
* 3.持有抽象接口的引用
*/
public abstract class Decorator implements Drink{
//定义私有饮品引用
private Drink drink;
//通过构造来创建抽象接口的引用
public Decorator(Drink drink){
this.drink = drink;
}
@Override
public double price() {
return drink.price();
}
@Override
public String description() {
return drink.description();
}
}
package cn.homyit.designpattern.decorator;
/**
* ConcreteDecorator
* 具体装饰
* 红豆豆浆
*/
public class RedBeanSoya extends Decorator{
public RedBeanSoya(Drink drink) {
super(drink);
}
//重写价格
@Override
public double price() {
return super.price()+3.2;
}
//重写描述
@Override
public String description() {
return super.description()+"+红豆";
}
}
package cn.homyit.designpattern.decorator;
/**
* ConcreteDecorator
* 具体装饰
* 鸡蛋豆浆
*/
public class EggSoya extends Decorator{
public EggSoya(Drink drink) {
super(drink);
}
//重写价格
@Override
public double price() {
return super.price()+3.9;
}
//重写描述
@Override
public String description() {
return super.description()+"+鸡蛋";
}
}
package cn.homyit.designpattern.decorator;
/**
* ConcreteDecorator
* 具体装饰
* 糖豆浆
*/
public class SugarSoya extends Decorator{
public SugarSoya(Drink drink) {
super(drink);
}
//重写价格
@Override
public double price() {
return super.price()+2.1;
}
//重写描述
@Override
public String description() {
return super.description()+"加糖";
}
}
package cn.homyit.designpattern.decorator;
/**
* 测试类
*/
public class Test {
public static void main(String[] args) {
//创建豆浆对象
Drink soya = new Soya();
System.out.println(soya.price());
System.out.println(soya.description());
System.out.println("----------------------");
//创建红豆豆浆
Drink redBean = new RedBeanSoya(soya);
System.out.println(redBean.price());
System.out.println(redBean.description());
System.out.println("----------------------");
//创建鸡蛋豆浆
Drink egg = new EggSoya(soya);
System.out.println(egg.price());
System.out.println(egg.description());
System.out.println("----------------------");
//创建糖豆浆
Drink sugar = new SugarSoya(soya);
System.out.println(sugar.price());
System.out.println(sugar.description());
System.out.println("----------------------");
//创建红豆鸡蛋豆浆
Drink eggRedBean = new EggSoya(redBean);
System.out.println(eggRedBean.price());
System.out.println(eggRedBean.description());
System.out.println("----------------------");
}
}
打印结果如下:
5.0
纯豆浆
----------------------
8.2
纯豆浆+红豆
----------------------
8.9
纯豆浆+鸡蛋
----------------------
7.1
纯豆浆加糖
----------------------
12.1
纯豆浆+红豆+鸡蛋
----------------------