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

本文讲下什么是装饰模式。装饰模式类图如下:
装饰模式这里有父组件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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值