当前位置: 代码迷 >> 综合 >> 设计模式-装饰者模式(Decorator Pattern)
  详细解决方案

设计模式-装饰者模式(Decorator Pattern)

热度:83   发布时间:2023-12-01 20:31:44.0

推荐: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

一个简单的装饰者模式例子就完成了,这种方法是不是比上一种方法更容易扩展,想加几个鸡蛋、几根香肠都可以,并不需要再添加类,如果煎饼还可以加培根,这里就只需要添加一个加培根业务的具体装饰者即可。

适用场景

  • 扩展一个类的功能或者给一个类添加附加职责。
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。

优点

  • 通过使用不同装饰类以及这些类的排列组合,可以实现不同的效果。
  • 符合开闭原则。
  • 装饰者模式和继承关系的目的都是要扩展原有对象的功能,但是装饰者模式可以提供比继承更多的灵活型。

缺点

  • 更多的代码,更多的类,增加程序的复杂性。
  • 动态装饰时、多层装饰时会使系统更复杂。
  • 越灵活也意味着更容易出错。

相关设计模式

  • 装饰者模式和代理模式: 装饰者模式关注的是对象功能的动态添加。而代理模式关注的是对对象的控制访问,对它的用户隐藏对象的具体信息。

  • 装饰者模式和适配器模式:装饰者模式和被装饰的类要实现同一个接口,或者装饰类是被装饰的类的子类。 适配器模式和被适配的类具有不同的接口。

如果有说错的地方,请大家不吝赐教(记得留言哦~~~~)。

  相关解决方案