JAVA设计模式讲解(原理+实例)---装饰模式

来源:互联网 发布:淘宝的漏洞赚钱方法 编辑:程序博客网 时间:2024/05/18 17:26

本文讲下什么是装饰模式。装饰模式类图如下:
装饰模式这里有父组件Component是一个抽象类或者一个接口,这个看具体业务的需求,ConcreteComponent是一个继承了父类(接口)的具体实现类,也就是被装饰的类。Decorator是装饰器,其实也是可有可无的,看具体业务,如果装饰器是一个抽象类,辣么它的存在就表示子类必须实现装饰器的某些方法,如果装饰器的某些方法已经自己实现了,说明子类可以实现也可以不实现其方法。装饰器下面的就是实际的用来装饰ConcreteComponent的装饰材料。


看一个具体例子
代码类之间的关系如下:
关系
解释:第一部分,是父类,之所以要这个父类是因为Mocha或者soy内部持有一个父类的引用,只有持有这个引用,才可以既覆盖父类(通过继承)的方法又装饰父类(通过调用父类的引用的相同的方法(不同的方法也可以调))的方法。第二部分,就是已经实现了父类大部分方法的子类,也就是被装饰的类(通过Mocha和Soy来增强)。第三部分,一个装饰器,用来表述哪些方法需要子类去实现(抽象类)。第四部分,装饰第二部分的类,可以在第二部分类的基础上,进行二次开发。
代码如下:

public abstract class Beverage {    protected String description = "Unknown Beverage";    public String getDescription() {        return description;    }    public abstract double cost();}
public class DarkRoast extends Beverage {    public DarkRoast() {        description = "DarkRoast";    }    public double cost() {        return .99;    }}
public abstract class CondimentDecorator extends Beverage {    public abstract String getDescription();}
public class Mocha extends CondimentDecorator {    Beverage beverage;    public Mocha(Beverage beverage) {        this.beverage = beverage;    }    public String getDescription() {        return beverage.getDescription() + ", Mocha";    }    public double cost() {        return .20 + beverage.cost();    }}
public class Whip extends CondimentDecorator {    Beverage beverage;    public Whip(Beverage beverage) {        this.beverage = beverage;    }    public String getDescription() {        return beverage.getDescription() + ", Whip";    }    public double cost() {        return .10 + beverage.cost();    }}
Beverage beverage2 = new DarkRoast();        beverage2 = new Mocha(beverage2);        //这里传入的beverage2不是Beverage beverage2 = new DarkRoast();而是经过修饰后的beverage2 = new Mocha(beverage2);每次传入的都是经过修饰后的        beverage2 = new Mocha(beverage2);        beverage2 = new Whip(beverage2);        System.out                .println(beverage2.getDescription() + " $" + beverage2.cost());

运行结果:
DarkRoast, Mocha, Mocha, Whip $1.49
运行过程如下图所示:
运行流程
下面解释下:

  1. 第一次new DarkRoast();的时候beverage2指向堆中的DarkRoast;
  2. 第二次beverage2 = new Mocha(beverage2)(第一个Mocha中有个成员变量Beverage beverage;),Mocha中的成员变量beverage指向了之前的beverage2,由于beverage2指向DarkRoast,也就是说Mocha中的成员变量beverage也指向DarkRoast。
  3. 再次,beverage2 = new Mocha(beverage2),第二个Mocha中的成员变量beverage也指向之前的beverage2 ,由于beverage2 还是指向第一个Mocha,所以第二个Mocha中的beverage也指向第一个Mocha,这里之所以都可以指向Mocha或者beverage2是因为他们发父类型是一样的。
  4. 最后,beverage2 = new Whip(beverage2);原理也是一样。其实,这里的beverage2只是用来接收不同的对象,保持一个引用。也可以每次都使用一个新的Beverage beverageNew来接收,这样的话,每次传入的就是这个新的beverageNew。使用每次new一个新对象的流程图如下:
    流程2
    打印结果也是一样。
    当然,也可以这样写代码:
        Beverage beverage2 = new DarkRoast();        beverage2 = new Whip(new Mocha(new Mocha(beverage2)));        System.out                .println(beverage2.getDescription() + " $" + beverage2.cost());

这样写的代码的流程图其实就是少了两条指向new出来的Mocha对象的虚线。

0 0