装饰者模式

2018-11-21  本文已影响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元

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

最后给大家一个提醒

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

上一篇 下一篇

猜你喜欢

热点阅读