关于java:设计模式装饰者模式

31次阅读

共计 2348 个字符,预计需要花费 6 分钟才能阅读完成。

WX 搜寻:程序员个人修养 查看更多内容

装璜者模式(Decorator)

运行时扩大,远比编译期间的继承威力大。咱们将探讨如何应用对象组合的形式,做到在运行时装璜类。

利用继承设计子类的行为,是在编译时动态决定的,而且所有子类都会继承雷同的行为。然而,如果可能利用组合的做法扩大对象的行为,就能够在运行时动静地进行扩大,而不需批改现有代码。既然没有扭转现有代码,那么呈现 bug 的可能就不大幅升高。

设计准则

凋谢 - 敞开准则

类应该对外扩大开发,对批改敞开。

定义

装璜者模式动静地将责任附加到对象上。若要扩大性能,装璜者提供了比继承更有弹性的代替计划。

类图

代码实现

咱们以咖啡厅为例,来模仿一个装璜者模式的实现。

首先,咖啡厅售卖一种咖啡,这种咖啡原价是 ¥10,如果客户须要加糖的话,就须要加上糖的价格 ¥2,客户还能够抉择是否加牛奶,牛奶的价格是 ¥5。加糖或者咖啡都能够看做是对咖啡口味的装璜。

那么,在这个案例当中,咖啡就是被装璜者,糖和牛奶是两个装璜者,通过给咖啡装璜(这里是不同的口味,甜味或者牛奶味,亦或者两者都加),来售卖不同口味的咖啡,当然价格也会不同。

上面咱们用代码来实现:

package com.study.design.Decorator;

/**
 * 被装璜者抽象类
 */
public abstract class Coffe {

    /**
     * 计算价格的办法
     * @return
     */
    protected abstract int cost();}
package com.study.design.Decorator;

/**
 * 被装璜者对象
 * 原味咖啡,售价 ¥10
 */
public class OriginalCoffe extends Coffe{

    @Override
    protected int cost() {return 10;}
}
package com.study.design.Decorator;

public abstract class Decorator extends Coffe{

    // 被装璜者对象
    protected Coffe coffe;

    protected abstract int additional();}
package com.study.design.Decorator;

/**
 * 装璜者
 * 加糖 ¥2
 */
public class Sugar extends Decorator{public Sugar(Coffe coffe){this.coffe = coffe;}

    @Override
    protected int cost() {return coffe.cost() + additional();}

    @Override
    protected int additional() {return 2;}
}
package com.study.design.Decorator;

/**
 * 装璜者
 * 加牛奶 ¥5
 */
public class Milk extends Decorator{public Milk(Coffe coffe){this.coffe = coffe;}

    @Override
    protected int cost() {return coffe.cost() + additional();}

    @Override
    protected int additional() {return 5;}
}
package com.study.design.Decorator;

public class DecoratorTest {public static void main(String[] args) {OriginalCoffe originalCoffe = new OriginalCoffe();
        System.out.println("原味咖啡价格:" + originalCoffe.cost());
        Sugar sugar = new Sugar(originalCoffe);
        System.out.println("加糖后的价格:" + sugar.cost());
        Milk milk = new Milk(originalCoffe);
        System.out.println("加牛奶后的价格" + milk.cost());
        milk = new Milk(sugar);
        System.out.println("加牛奶加糖后的价格:" + milk.cost());

    }
}

相熟 AOP 的同学到这里应该会联想到,在装璜者中减少的新办法或者说性能,这不就像是 AOP 中的前置告诉、后置告诉么?

是的!不过 AOP 底层是通过动静代理实现的,动静代理与装璜者模式本质区别就是,前者关注的是对代理对象行为管制,不同的代理对象实现被代理对象行为的不同的管制,并且这些代理对象很少有组合的可能。

而后者侧重于对被装璜者性能的扩大。不同的装璜者为被装璜者削减不同的性能,并且这些装璜者能够任意嵌套组合。比方糖和牛奶能够同时增加。

Java I/O 中的装璜者模式

对于装璜者模式,最经典的就是 Java I/O 中的利用。理解了装璜者模式,再回头系统地看下无关 Java I/O 的源码就会晦涩很多。

以上展现了输出流的局部类图关系,输入流也是一样。但 Java I/O 也引出了装璜者模式的一个“毛病”:利用装璜者模式,经常会造成设计中有大量的小类,数量切实太多,可能会造成应用此 API 的开发人员的困扰。然而,如果理解了装璜者模式的原理,当前当应用他人的大量装璜的 API 时,就能够很容易的分别出他们的装璜者类时如何组织,以不便用包装形式获得想要的行为。

要点

  • 所有被装璜者和装璜者须要继承自对立的父类或者实现同一个接口
  • 装璜者须持有一个被装璜者接口类型的对象
  • 装璜者能够在被装璜者前 / 后加上本人的行为,甚至将被装璜者的行为整个取代掉,而达到特定的目标
  • 装璜者会导致设计中呈现许多小对象,如果适度应用,会让程序变得很简单

WX 搜寻:程序员个人修养 查看更多内容

正文完
 0