欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式(三)The_Decorator_Pattern(装饰者模式)

程序员文章站 2022-03-21 23:46:25
...

the Decorator Pattern

概述

装饰者模式实现的功能是在运行的时候使用object composition对象组合,从而达能在不改变代码的情况下给对象以新的功能。

问题提出

如果你想要设计一个饮品的类,那么你可能设计如下:

  • 一个抽象的Beverage
    • description,是一个实例变量,可以使String字符串,每个继承的子类都有设置
    • getDescription()
    • cost(); 是一个抽象的方法,每个子类都需要自己定义他们的价格。

这样在每次新添加一个款饮品时,就可以直接继承并且重写cost();

这看起来很好,但是对于维护来说确实一个噩梦。

比如如果牛奶的价格上涨,那么所有关于牛奶做原材料的饮品都需要价格上调。
而且对于咖啡来说,可以添加不同的调味品,那么对于不同调味品的组合,就需要产生不同的子类,导致子类太多!

那么是否可以在超类/父类中实例化这些调味品,然后继承跟踪这些呢?
新:
Beverage:

  • description
  • milk boolean型
  • soy
  • mocha
  • whip
  • getDescription()
  • cost() 现在cost方法不再是抽象的,这样能够计算通过调味品的状态来计算价格,子类也将会重写cost,但是他们会先调用super版本,来计算添加调配品后的基础价格。
  • hasMilk();
  • setMilk();
  • hasSoy();
  • 等等

原则:The Open-Closed Principle

Classes should be open for extension, but closed for modification;
类的设计应该对扩展开放,对修改关闭。

我们的目标是让类容易去在未修改代码的情况下去添加新的行为。一旦我们达成这样的设计,对于添加新的功能需求是平稳的并且可恢复的。

**注意:**小心选择需要扩展的代码区,到处使用Open-Closed Principle是没必要切浪费资源,增加代码复杂度,难于理解。

装饰模式

上边的解决方法仍然不是很好,可能产生类爆炸,不灵活的设计,或者在基类中添加一些不适用与所有子类的功能。

装饰者模式:对于咖啡的例子来说,我们在运行时动态添加调剂品,例如 :

  1. 创建一个DarkRoast子类
  2. 使用Mocha(摩卡)的类装饰一下
  3. 使用Whip(打泡)装饰
  4. 调用cost()函数,依靠代理(delegation)来添加调配品的价格

如何实现装饰?delegation是如何产生的?

按照包装的思想考虑:

  1. 开始于DarkRoash 对象
  2. 消费者想要摩卡,我们构建一个Mocha的对象,并且包装DarkRoash对象。
  3. Whip同理
    4.计算cost()时使用递归的思想。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LPQZHhOj-1576402836142)(_v_images/20191209112130384_10807.png =652x)]

实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ai43ULJI-1576402836144)(_v_images/20191209124139793_24032.png)]
有两个主要的基类,都是抽象类,分别是Beverage和CondimentDecorator, 其中CondimentDecorator又继承Beverage。
所有的饮品都继承Beverage, 所有的添加剂/调味品都继承CondimentDecorator.
在具体的CondimentDecorator的子类中,需要处理包装的功能。并且要保存Beverage变量。

//基类
public abstract class Beverage {
    String description = “Unknown Beverage”;
    public String getDescription() {
    return description;
    }
    public abstract double cost();
}

//装饰器基类,继承Beverage
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();    
}

/*一些子类*/
//特浓
public class Espresso extends Beverage {
    public Espresso() {
        description = “Espresso”;
    }
    public double cost() {
        return 1.99;
    }
}

public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = “House Blend Coffee”;
    }
    public double cost() {
        return .89;
    }
}

/*调味品*/
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 StarbuzzCoffee {
    public static void main(String args[]) {
        //特浓
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription()
                + “ $” + beverage.cost());
        
        //DarkRoast
        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        System.out.println(beverage2.getDescription()
                + “ $” + beverage2.cost());
        
        //HouseBlend();
        Beverage beverage3 = new HouseBlend();
        beverage3 = new Soy(beverage3);
        beverage3 = new Mocha(beverage3);
        beverage3 = new Whip(beverage3);
        System.out.println(beverage3.getDescription()
                + “ $” + beverage3.cost());
    }
}

简单来说,就是把能够组合的分离出来,但是都有共同的基类。
设计模式(三)The_Decorator_Pattern(装饰者模式)

设计模式(三)The_Decorator_Pattern(装饰者模式)

相关标签: coding