推荐:Java设计模式汇总
装饰者模式
定义
在不改变原有对象的基础上,将功能附加到原有功能上,进行功能的扩展。
装饰者模式提供了比继承更有弹性的替代方案。
类型
结构型。
例子
这里举煎饼的例子,大家吃煎饼一般会加东西吧,比如鸡蛋、香肠等。
首先看看由普通继承来实现这个例子。
Battercake类,煎饼类。
package com.kaven.design.pattern.structural.decorator;public class Battercake {
protected String getDesc(){
return "煎饼";}protected int cost(){
return 8;}
}
BattercakeWithEgg类,加鸡蛋的煎饼类,继承了Battercake类。
package com.kaven.design.pattern.structural.decorator;public class BattercakeWithEgg extends Battercake {
public String getDesc() {
return super.getDesc()+" 加一个鸡蛋";}public int cost() {
return super.cost()+1;}
}
BattercakeWithSausage类,加香肠的煎饼类,继承了Battercake类。
package com.kaven.design.pattern.structural.decorator;public class BattercakeWithSausage extends BattercakeWithEgg {
@Overridepublic String getDesc() {
return super.getDesc()+" 加一根香肠";}@Overridepublic int cost() {
return super.cost()+2;}
}
应用层代码:
package com.kaven.design.pattern.structural.decorator;public class Test {
public static void main(String[] args) {
Battercake battercake = new Battercake();System.out.println(battercake.getDesc()+" 销售价格:"+battercake.cost());BattercakeWithEgg battercakeWithEgg = new BattercakeWithEgg();System.out.println(battercakeWithEgg.getDesc()+" 销售价格:"+battercakeWithEgg.cost());BattercakeWithSausage battercakeWithSausage = new BattercakeWithSausage();System.out.println(battercakeWithSausage.getDesc()+" 销售价格:"+ battercakeWithSausage.cost());}
}
输出:
煎饼 销售价格:8
煎饼 加一个鸡蛋 销售价格:9
煎饼 加一个鸡蛋 加一根香肠 销售价格:11
如果我需要加两个鸡蛋、两根香肠的煎饼呢?
此时,我们就需要再实现一个类来满足需求,但是这样的需求多种多样,显然用普通继承的方法来实现这个例子并不好。
改进
ABattercake类,抽象煎饼类。
package com.kaven.design.pattern.structural.decorator.v2;public abstract class ABattercake {
protected abstract String getDesc();protected abstract int cost();
}
Battercake类,具体煎饼类,继承ABattercake类。
package com.kaven.design.pattern.structural.decorator.v2;public class Battercake extends ABattercake {
protected String getDesc() {
return "煎饼";}protected int cost() {
return 8;}
}
AbstractDecorator类,抽象装饰者类,继承ABattercake类。
package com.kaven.design.pattern.structural.decorator.v2;//根据业务来判断抽象装饰者是否要定义成抽象类
public class AbstractDecorator extends ABattercake {
private ABattercake aBattercake;public AbstractDecorator(ABattercake aBattercake) {
this.aBattercake = aBattercake;}protected String getDesc() {
return this.aBattercake.getDesc();}protected int cost() {
return this.aBattercake.cost();}
}
EggDecorator类,实现加鸡蛋业务的具体装饰者,继承AbstractDecorator类。
package com.kaven.design.pattern.structural.decorator.v2;public class EggDecorator extends AbstractDecorator {
public EggDecorator(ABattercake aBattercake) {
super(aBattercake);}@Overrideprotected String getDesc() {
return super.getDesc()+" 加一个鸡蛋";}@Overrideprotected int cost() {
return super.cost()+1;}
}
SausageDecorator类,实现加香肠业务的具体装饰者,继承AbstractDecorator类。
package com.kaven.design.pattern.structural.decorator.v2;public class SausageDecorator extends AbstractDecorator{
public SausageDecorator(ABattercake aBattercake) {
super(aBattercake);}@Overrideprotected String getDesc() {
return super.getDesc()+" 加一根香肠";}@Overrideprotected int cost() {
return super.cost()+2;}
}
应用层代码:
package com.kaven.design.pattern.structural.decorator.v2;public class Test {
public static void main(String[] args) {
ABattercake aBattercake;aBattercake = new Battercake();aBattercake = new EggDecorator(aBattercake);aBattercake = new EggDecorator(aBattercake);aBattercake = new SausageDecorator(aBattercake);System.out.println(aBattercake.getDesc()+" 销售价格:"+aBattercake.cost());}
}
输出:
煎饼 加一个鸡蛋 加一个鸡蛋 加一根香肠 销售价格:12
一个简单的装饰者模式例子就完成了,这种方法是不是比上一种方法更容易扩展,想加几个鸡蛋、几根香肠都可以,并不需要再添加类,如果煎饼还可以加培根,这里就只需要添加一个加培根业务的具体装饰者即可。
适用场景
- 扩展一个类的功能或者给一个类添加附加职责。
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
优点
- 通过使用不同装饰类以及这些类的排列组合,可以实现不同的效果。
- 符合开闭原则。
- 装饰者模式和继承关系的目的都是要扩展原有对象的功能,但是装饰者模式可以提供比继承更多的灵活型。
缺点
- 更多的代码,更多的类,增加程序的复杂性。
- 动态装饰时、多层装饰时会使系统更复杂。
- 越灵活也意味着更容易出错。
相关设计模式
-
装饰者模式和代理模式: 装饰者模式关注的是对象功能的动态添加。而代理模式关注的是对对象的控制访问,对它的用户隐藏对象的具体信息。
-
装饰者模式和适配器模式:装饰者模式和被装饰的类要实现同一个接口,或者装饰类是被装饰的类的子类。 适配器模式和被适配的类具有不同的接口。
如果有说错的地方,请大家不吝赐教(记得留言哦~~~~)。