装饰者模式的应用场景
装饰者模式是指在不改变原有对象的基础上,将功能附加到对象上,提供了比继承更有弹性的替代策略。适用于以下场景:
1.用于扩展一个类的功能或给一个类添加附加职责。
2.动态的给一个对象添加功能,这些功能可以再动态的撤销。
下列以煎饼摊为例(继承模式实现):
煎饼类:
package decorator;
/**
* Created by Lenovo on 2019-7-20.
*/
public class Battercake {
protected String getMsg(){
return "煎饼";
}
public int getPrice(){
return 5;
}
}
加鸡蛋:
package decorator;
/**
* Created by Lenovo on 2019-7-20.
*/
public class BattercakeWithEgg extends Battercake {
@Override
protected String getMsg() {
return super.getMsg()+"1个鸡蛋";
}
@Override
public int getPrice() {
return super.getPrice()+1;
}
}
加鸡蛋加香肠
package decorator;
/**
* Created by Lenovo on 2019-7-20.
*/
public class BattercakeWithEggAndSausage extends BattercakeWithEgg {
@Override
protected String getMsg() {
return super.getMsg()+"一根香肠";
}
@Override
public int getPrice() {
return super.getPrice()+2;
}
}
测试类
package decorator;
/**
* Created by Lenovo on 2019-7-20.
*/
public class BattercakeTest {
public static void main(String[] args){
Battercake battercake=new Battercake();
System.out.println(battercake.getMsg()+",总价格:"+battercake.getPrice());
Battercake battercakeWithEgg=new BattercakeWithEgg();
System.out.println(battercakeWithEgg.getMsg()+",总价格:"+battercakeWithEgg.getPrice());
Battercake battercakeWithEggAndSausage=new BattercakeWithEggAndSausage();
System.out.println(battercakeWithEggAndSausage.getMsg()+",总价格:"+battercakeWithEggAndSausage.getPrice());
}
}
从以上例子可以发现,如果用户需要2个鸡蛋加一根香肠,那么我们用现有的类结构是创建不出来的,除非再定制化创建一个类,这样一直加定制显然是不科学的。那么下面我们就用装饰者模式来解决上面的问题。
煎饼抽象类
package decoratorV2;
/**
* Created by Lenovo on 2019-7-20.
*/
public abstract class Battercake {
protected abstract String getMsg();
protected abstract int getPrice();
}
基本煎饼套餐
package decoratorV2;
/**
* Created by Lenovo on 2019-7-20.
*/
public class BaseBattercake extends Battercake {
@Override
protected String getMsg() {
return "煎饼";
}
@Override
protected int getPrice() {
return 5;
}
}
扩展套餐的抽象装饰者
package decoratorV2;
/**
* Created by Lenovo on 2019-7-20.
*/
public abstract class BattercakeDecorator extends Battercake {
//静态代理,委派
private Battercake battercake;
public BattercakeDecorator(Battercake battercake) {
this.battercake = battercake;
}
@Override
protected String getMsg() {
return this.battercake.getMsg();
}
@Override
protected int getPrice() {
return this.battercake.getPrice();
}
}
鸡蛋装饰者
package decoratorV2;
/**
* Created by Lenovo on 2019-7-20.
*/
public class EggDecorator extends BattercakeDecorator {
public EggDecorator(Battercake battercake) {
super(battercake);
}
protected void doSomething(){
}
@Override
protected String getMsg() {
return super.getMsg()+"1个鸡蛋";
}
@Override
protected int getPrice() {
return super.getPrice()+1;
}
}
香肠测试类
package decoratorV2;
/**
* Created by Lenovo on 2019-7-20.
*/
public class SausageDecorator extends BattercakeDecorator {
public SausageDecorator(Battercake battercake) {
super(battercake);
}
protected void doSomething(){
}
@Override
protected String getMsg() {
return super.getMsg()+"+1根香肠";
}
@Override
protected int getPrice() {
return super.getPrice()+2;
}
}
测试类
package decoratorV2;
/**
* Created by Lenovo on 2019-7-20.
*/
public class BattercakeTest {
public static void main(String [] args){
Battercake battercake;
//路边摊买一个煎饼
battercake =new BaseBattercake();
//加鸡蛋
battercake=new EggDecorator(battercake);
//加香肠
battercake=new SausageDecorator(battercake);
//跟静态代理最大的区别是职责不同
//静态代理不一定要满足is-a的关系
//静态代理会做功能代理,同一个职责变得不一样
//装饰者更多考虑是扩展
System.out.println(battercake.getMsg()+",总价:"+battercake.getPrice());
}
}
相关的类图:
装饰者的优点:
1.装饰者是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。
2.通过使用不同装饰类以及这些装饰类的排列组合,可以实现不同效果。
3.装饰者完全遵守开闭原则。
缺点:
1.会出现更多的代码,更多的类,增加程序复杂类。
2.动态装饰时,多层装饰时会更复杂。