美文网首页
装饰者模式

装饰者模式

作者: 满天星爱我 | 来源:发表于2018-11-21 23:35 被阅读14次

定义

动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案

设计原则

  • 类应该对外扩展开放,对修改关闭
    允许类容易扩展,在不修改现有代码的情况下,就可搭配新的行为。

要点

  • 装饰者和被装饰对象具有相同的超类型
  • 可以一个或多个装饰者包装一个对象
  • 在任何需要原始对象的场合,都可以用装饰过的对象代替它
  • 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的
  • 装饰者必须能取代被装饰者

下面是一个例子。

案例

街上有很多小摊,其中最常见的就是煎饼果子摊位,煎饼可以加火腿,加鸡蛋,加肉,在这里煎饼就是原类,而鸡蛋、火腿、等就是装饰者,他们都继承共同的超类,超类的代码如下:

 //所有类的超类型
public interface IPancake {
//用来描述此类
  String getDescription();
//价钱
  double cost();
}

很简单,就是一个接口,定义了两个方法getDescription()cost()
接下来我们做一张煎饼,代码如下:

/**
* 煎饼
*/
public class Pancake implements IPancake{
private String mDescription = "煎饼";

@Override
public String getDescription() {
    return mDescription;
}

/**
 * 单张煎饼4元
 * @return
 */
@Override
public double cost() {
    return 4.0;
}

我们定义它的价钱为4块钱,名字为煎饼,然后一张不加任何东西的煎饼就完成了。

接下来我们该做装饰类了,首先我们需要一个装饰者抽象类,然后让所有的具体装饰者继承此类,代码如下:

/**
 * 装饰抽象类
*/
public abstract class Decorator implements IPancake{
    protected IPancake pancake;
    public Decorator(IPancake pancake) {
        this.pancake = pancake;
  }

  public abstract String getDescription();
  }

该抽象类提供了一个构造方法,将要装饰的对象传进来,可以在此对象委托前后加上自己的行为,接下来写一个鸡蛋装饰者,代码如下:

public class EggDecorator extends Decorator {

public EggDecorator(IPancake pancake) {
    super(pancake);
}

@Override
public String getDescription() {
    return"鸡蛋"+pancake.getDescription();
}

@Override
public double cost() {
    return 1.0 + pancake.cost();
}
}

看到了吗?在构造方法中传入要装饰的对象,而pancake变量是在父类里声明的,这样子类也可以使用了,然后再看getDescription()cost()方法中,把被装饰者的描述和价钱都附加到了装饰者的描述和价钱中,以达到我们的目的。

同理,火腿装饰者代码类似,如下所示:

public class HamDecorator extends Decorator{

public HamDecorator(IPancake pancake) {
    super(pancake);
}

@Override
public String getDescription() {
    return "火腿" + pancake.getDescription();
}

@Override
public double cost() {
    return 1.5 + pancake.cost();
}
}

现在我想要:

  • 煎饼
  • 鸡蛋煎饼
  • 火腿煎饼
  • 鸡蛋火腿煎饼

我们在main方法中做测试,代码如下:

public class DecoratorTest {

public static void main(String[] args){
 //什么也不加
 IPancake pancake = new Pancake();
 System.out.println(pancake.getDescription()+" 价钱: " + pancake.cost());
 //加一个鸡蛋
 EggDecorator eggDecorator = new EggDecorator(pancake);
 System.out.println(eggDecorator.getDescription()+" 价钱: " + eggDecorator.cost());
 //加一个火腿
 HamDecorator hamDecorator = new HamDecorator(pancake);
 System.out.println(hamDecorator.getDescription()+" 价钱: " + hamDecorator.cost());
 //加鸡蛋、火腿的煎饼
 pancake = new HamDecorator(eggDecorator);
 System.out.println(pancake.getDescription()+" 价钱: " + pancake.cost());
}
}

打印结果:

煎饼 价钱: 4.0元
鸡蛋煎饼 价钱: 5.0元
火腿煎饼 价钱: 5.5元
火腿鸡蛋煎饼 价钱: 6.5元

这样,我们需要的东西都出来了,算算价钱也完全正确。

最后给大家一个提醒

装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂,根据情况合理的使用设计模式才是王道。

相关文章

  • 如何利用装饰者模式在不改变原有对象的基础上扩展功能

    目录 什么是装饰者模式 普通示例 装饰者模式示例 类图关系 装饰者模式使用场景 装饰者模式优点 装饰者模式缺点 什...

  • 装饰者模式

    装饰者模式 装饰者模式和适配器模式对比 装饰者模式 是一种特别的适配器模式 装饰者与被装饰者都要实现同一个接口,主...

  • java IO 的知识总结

    装饰者模式 因为java的IO是基于装饰者模式设计的,所以要了解掌握IO 必须要先清楚什么事装饰者模式(装饰者模式...

  • 设计模式-装饰者模式

    装饰者模式概念: 装饰者模式又名包装(Wrapper)模式。装饰者模式以对客户端透明的方式扩展对象的功能,是继承关...

  • java - 装饰者模式

    装饰者模式 装饰者模式:动态将责任添加到对象上。如果需要扩展功能,装饰者提供了比继承更有弹性的解决方案。装饰者模式...

  • 设计模式之装饰者模式(Decorator Pattern)

    What: 装饰者模式又名包装(Wrapper)模式。装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提...

  • 装饰者(Decorator)模式

    装饰者(Decorator)模式装饰模式又名包装(Wrapper)模式。装饰模式是继承关系的一个替代方案。装饰模式...

  • 2、装饰者模式

    装饰者模式 一、基本概念 二、结构 三、案例1、装饰者模式案例2、JavaIO中使用装饰者模式 四、总结 一、基本...

  • PHP的设计模式-装饰者模式

    装饰者模式 装饰者模式 装饰者模式类似蛋糕,有草莓味、奶酪等种类,但是它们的核心都是蛋糕。 不断地将对象添加装饰的...

  • 设计模式 | 装饰者模式及典型应用

    前言 本文的主要内容: 介绍装饰者模式 示例 源码分析装饰者模式的典型应用Java I/O 中的装饰者模式spri...

网友评论

      本文标题:装饰者模式

      本文链接:https://www.haomeiwen.com/subject/fcnhqqtx.html