美文网首页
理解装饰器模式

理解装饰器模式

作者: 梦的飞翔_862e | 来源:发表于2018-11-16 18:39 被阅读0次
概念描述

装饰器模式是一种结构型模式,它是对现有对象的一个包装,然后在包装类中加入新的功能。

场景描述

考虑这样一个场景:咖啡店中目前有咖啡,比如espresso,americano,decaf,客人根据自己的喜好,可以选择加糖,加奶或者两者都加,也可以什么都不加,当然,根据加入原料的不同价格也不相同。

设计一:

以直观的想法去设计这样一个结构,应该是


Coffee.java
public class Coffee {
    private String description;
    private double cost;
    public Coffee(String description, double cost) {
        this.description = description;
        this.cost = cost;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public double getCost() {
        return cost;
    }
    public void setCost(double cost) {
        this.cost = cost;
    }
}
Americano.java
public class Americano extends  Coffee{
    public Americano(){
        super("americano",12);
    }
}
SugarAmericano.java
public class SugarAmericano  extends Coffee{

    public SugarAmericano(){
        super("sugarAmericano",15);
    }
}

上面的结构一个很明显的缺陷是,咖啡和配料有很多种组合,需要将每一种组合都定义为一个类,这样的结构会变的庞大而不好维护。

设计二:

第二种改进的方式,可以将配料定义在超类中,在子类中通过条件判断语句,来组成不同的组合

Coffee.java
public class Coffee {
    private String description;
    private double cost;

    private boolean sugar;
    private boolean milk;

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public double getCost() {
        return cost;
    }

    public void setCost(double cost) {
        this.cost = cost;
    }

    public boolean isSugar() {
        return sugar;
    }

    public void setSugar(boolean sugar) {
        this.sugar = sugar;
    }

    public boolean isMilk() {
        return milk;
    }

    public void setMilk(boolean milk) {
        this.milk = milk;
    }
}
Americano.java
public class Americano extends Coffee {
    public Americano(){
        super();
    }

    @Override
    public String getDescription() {
        StringBuffer desc= new StringBuffer();
        if(isSugar()){
            desc.append("add sugar,");
        }
        if(isMilk()){
            desc.append("add milk ,");
        }
        desc.append("americano");
       return desc.toString();
    }



    @Override
    public double getCost() {
       double cost= 3.0;
       if(isMilk()){
           cost+=1;
       }
       if(isSugar()){
           cost+=3;
       }

       return cost;
    }
}
TestApp.java
public class TestApp {

    public static void main(String[] args) {
        Coffee coffee = new Americano();
        coffee.setMilk(true);
        System.out.println(coffee.getDescription());
        System.out.println(coffee.getCost());
        coffee.setSugar(true);
        System.out.println(coffee.getDescription());
        System.out.println(coffee.getCost());
    }
}

设计二中的结构比第一种结构简单很多,但是如果新增一种配料,父类和子类都需要做相应的修改,这违反了开放封闭原则。

设计三:

使用装饰器设计模式后,项目结构调整为:



从图中可以看出,CoffeeDecorator是一个抽象装饰器,需要继承和引用抽象主体类。因为装饰器的本体仍然是Coffee

Coffee.java
public abstract class Coffee {
    private String description;
    private double cost;
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

    public  double getCost(){
        return this.cost;
    }

    public void setCost(double cost) {
        this.cost = cost;
    }
}
//具体的主体Americano 
public class Americano extends Coffee {

    public Americano(){
        super();
        super.setCost(3);
        super.setDescription("americano");
    }
}
//具体的主体
public class Espresso extends Coffee {

    public Espresso(){
        super();
        super.setCost(14);
        super.setDescription("espresso");
    }
}
//抽象装饰器
public abstract class CoffeeDecorator extends Coffee {

    private Coffee coffee;

    public CoffeeDecorator(Coffee coffee){
        this.coffee = coffee;
    }

    public double getCost(){
        return super.getCost()+coffee.getCost();
    }

    public String getDescription(){
        return super.getDescription()+","+coffee.getDescription();
    }
}
//具体装饰器
public class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee){
        super(coffee);
        super.setCost(5);
        super.setDescription("add milk");
    }
}
public class SugarDecorator extends CoffeeDecorator{

    public SugarDecorator(Coffee coffee){
        super(coffee);
        super.setCost(2);
        super.setDescription(" add sugar");

    }


}
//TestApp.java
public class TestApp {
    public static void main(String[] args) {
        //单品
        Coffee americano = new Americano();
        System.out.println("americano:"+americano.getCost());
        System.out.println("americano:"+americano.getDescription());
        //加入糖
        americano = new SugarDecorator(americano);
        System.out.println("sugar americano:"+americano.getCost());
        System.out.println("sugar americano:"+americano.getDescription());
        //再加入牛奶
        americano = new MilkDecorator(americano);
        System.out.println("sugar milk americano:"+americano.getCost());
        System.out.println("sugar milk  americano:"+americano.getDescription());
    }
}

java中的装饰器:

Java中的流是典型的装饰器模式,以输入流为例,FileInputStream是具体的主体,InputStream是抽象主体



同样的具体实体还有ByteArrayInputStream和StringBufferInputStream 。
输入流的抽象装饰器是FilterInputStream ,具体装饰器如BufferedInputStream,DataInputStream等


注意点

软件设计的原则:对修改封闭,对扩展开放
装饰器的优点:可以动态扩展一个对象的功能,比如咖啡Americano单品, 可以加糖,可以加奶,可以两者都加,这个过程,可以在运行时决定如何自由组合。
缺点:多层继承,结构稍复杂。

代码实例在https://github.com/jxl198/designPattern/tree/master/decorator

相关文章

  • Python装饰器模式

    标签: python|设计模式|装饰器模式 引子 对于装饰器模式我正在一点一点的理解........使用对象组合的...

  • Java设计模式——装饰器模式

    Java设计模式之装饰器模式 回顾 上一次分享的组合模式相信大家已经理解其中的精髓,那么这次跟大家聊聊装饰器模式。...

  • 六、门面模式与装饰器模式详解

    8.门面模式 8.1.课程目标 1、掌握门面模式和装饰器模式的特征和应用场景 2、理解装饰器模式和代理模式的根本区...

  • 理解装饰器模式

    概念描述 装饰器模式是一种结构型模式,它是对现有对象的一个包装,然后在包装类中加入新的功能。 场景描述 考虑这样一...

  • 装饰器模式

    一、装饰器模式介绍 二、装饰器模式代码实例

  • 9、结构型模式-装饰器设计模式

    1、如虎添翼的设计模式-装饰器设计模式 简介:讲解-装饰器设计模式介绍和应用场景 装饰器设计模式(Decorato...

  • ES7装饰器详解

    本文将从以下几个角度解析装饰器: 一、什么是装饰器模式: 要想正确理解设计模式,首先必须明确它是为了解决什么问题而...

  • 2021-07-26 装饰器模式与代理模式

    装饰器模式 定义 装饰器模式(Decorator Pattern)也叫包装模式(Wrapper Pattern),...

  • 1.装饰器模式

    装饰器模式 什么是装饰器模式? 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,...

  • thinking in Swift:重新审视装饰器模式

    thinking in Swift:重新审视装饰器模式 thinking in Swift:重新审视装饰器模式

网友评论

      本文标题:理解装饰器模式

      本文链接:https://www.haomeiwen.com/subject/uxipfqtx.html