zoukankan      html  css  js  c++  java
  • 设计模式(3)装饰者模式

    我们到咖啡店喝咖啡的时候,往往会根据各自的口味去选择咖啡和各种配料,比如咖啡可以选择综合、焙、低咖啡因、浓缩,配料可以选搭牛奶、摩卡、豆浆、奶泡。这个情境下就可以使用装饰者模式,用配料对咖啡进行装饰,组合成不同的咖啡。 

    装饰者模式——动态的将职责附加到对象上。想要扩展功能,装饰者模式是有别于继承的另一种选择。

    装饰者和被装饰者对象有相同的超类,可以用一个或多个装饰者装饰一个对象,装饰者可以在被装饰者的行为之前或之后,加上自己的行为,从而达到特定的目的。

    比如咖啡和配料都继承于一个超类Beverage,首先最底层是一个咖啡对象,然后一层层的用配料去装饰咖啡对象,最终得到了一个被装饰完成的对象。

    下面看下代码

    装饰者和被装饰在的超类

    public abstract class Beverage {
    
        /**
         * 大小
         */
        private SizeEnum size;
        /**
         * 描述
         *
         * @return 描述
         */
        public abstract String getDescription();
    
        /**
         * 花费
         *
         * @return 花费
         */
        public abstract double cost();
    
        public SizeEnum getSize() {
            return size;
        }
    
        public void setSize(SizeEnum size) {
            this.size = size;
        }
    }

    装饰者的父类

    public class CondimentDecorator extends Beverage{
        @Override
        public String getDescription() {
            return null;
        }
    
        @Override
        public double cost() {
            return 0;
        }
    }

    杯子大小的枚举

    public enum SizeEnum {
    
        /**
         * 小杯
         */
        TALL(1, "小杯"),
        /**
         * 中杯
         */
        GRANDE(2, "中杯"),
        /**
         * 大杯
         */
        VENTI(3, "大杯");
    
        SizeEnum(int value, String caption) {
            this.value = value;
            this.caption = caption;
        }
    
        /**
         * 大小
         */
        private int value;
        /**
         * 描述
         */
        private String caption;
    
        public int getValue() {
            return value;
        }
    
        public void setValue(int value) {
            this.value = value;
        }
    
        public String getCaption() {
            return caption;
        }
    
        public void setCaption(String caption) {
            this.caption = caption;
        }
    }

    几个继承了超类的咖啡类

    public class DarkRoast extends Beverage {
    
        public DarkRoast(SizeEnum sizeEnum) {
            super.setSize(sizeEnum);
        }
    
        @Override
        public String getDescription() {
            return "DarkRoast";
        }
    
        @Override
        public double cost() {
            return 0.99;
        }
    }
    public class Decaf extends Beverage {
    
        public Decaf(SizeEnum sizeEnum) {
            super.setSize(sizeEnum);
        }
    
        @Override
        public String getDescription() {
            return "Decaf";
        }
    
        @Override
        public double cost() {
            return 1.05;
        }
    }
    Decof
    public class Espresso extends Beverage {
    
        public Espresso(SizeEnum sizeEnum) {
            super.setSize(sizeEnum);
        }
    
        @Override
        public String getDescription() {
            return "Espresso";
        }
    
        @Override
        public double cost() {
            return 1.99;
        }
    }
    Espresso
    public class HouseBland extends Beverage {
    
        public HouseBland(SizeEnum sizeEnum) {
            super.setSize(sizeEnum);
        }
    
        @Override
        public String getDescription() {
            return "HouseBland";
        }
    
        @Override
        public double cost() {
            return 0.89;
        }
    }
    HouseBland

    装饰类

    public class Milk extends CondimentDecorator {
    
        private Beverage beverage;
    
        public Milk(Beverage beverage) {
            this.beverage = beverage;
        }
    
        @Override
        public String getDescription() {
            return "Milk, " + beverage.getDescription();
        }
    
        @Override
        public double cost() {
            return beverage.cost() + 0.10;
        }
    
        @Override
        public SizeEnum getSize() {
            return beverage.getSize();
        }
    }
    public class Mocha extends CondimentDecorator {
    
        private Beverage beverage;
    
        public Mocha(Beverage beverage) {
            this.beverage = beverage;
        }
    
        @Override
        public String getDescription() {
            return "Mocha, " + beverage.getDescription();
        }
    
        @Override
        public double cost() {
            return beverage.cost() + 0.20;
        }
    
        @Override
        public SizeEnum getSize() {
            return beverage.getSize();
        }
    }
    Mocha
    public class Soy extends CondimentDecorator {
    
        private Beverage beverage;
    
        public Soy(Beverage beverage) {
            this.beverage = beverage;
        }
    
        @Override
        public String getDescription() {
            return "Soy, " + beverage.getDescription();
        }
    
        @Override
        public double cost() {
            switch (this.getSize()) {
                case TALL:
                    return beverage.cost() + 0.10;
                case VENTI:
                    return beverage.cost() + 0.15;
                case GRANDE:
                    return beverage.cost() + 0.20;
                default:
                    return beverage.cost() + 0.10;
            }
        }
    
        @Override
        public SizeEnum getSize() {
            return beverage.getSize();
        }
    }
    Soy
    public class Whip extends CondimentDecorator {
    
        private Beverage beverage;
    
        public Whip(Beverage beverage) {
            this.beverage = beverage;
        }
    
        @Override
        public String getDescription() {
            return "Whip, " + beverage.getDescription();
        }
    
        @Override
        public double cost() {
            return beverage.cost() + 0.10;
        }
    
        @Override
        public SizeEnum getSize() {
            return beverage.getSize();
        }
    }
    Whip

     测试

    public static void main(String[] args) {
            Beverage beverage1 = new Espresso(SizeEnum.GRANDE);
            System.out.println(beverage1.getSize().getCaption() + " " + beverage1.getDescription() + "  cost: " + beverage1.cost());
            Beverage beverage2 = new DarkRoast(SizeEnum.VENTI);
            beverage2 = new Mocha(beverage2);
            beverage2 = new Mocha(beverage2);
            beverage2 = new Milk(beverage2);
            System.out.println(beverage2.getSize().getCaption() + " " + beverage2.getDescription() + "  cost: " + beverage2.cost());
        }

    输出

    装饰者模式的运用有很多,例如Java I/O 中 BufferedInputStream, LineNumberInputStream扩展自FileInputStream,而FileInputStream是一个抽象的装饰类。

    装饰者模式给我们带来了一种新的视角,除了使用继承,装饰者模式也可以对行为进行扩展。可以用无数的装饰者包装一个组件,但是装饰者模式会导致设计中出现许多的小对象,如果过渡使用的话,会让程序变得异常复杂。

  • 相关阅读:
    重启远程windows计算机
    web.xml文件的作用及基本配置
    DB2编码问题而导致连接不上上数据库
    合理使用表空间
    自动做题
    怎么给二年级小学生讲鸡兔同笼问题
    DB2 性能分析工具介绍:Event Monitor 篇(摘自IBM官方)
    delphi 对应 c# 的一些函数及类型的转换方法(从网络摘录)
    DB2 基础: 使用重定向恢复克隆 DB2 数据库(部分从IBM官方网站引用)
    response.setContentType()的作用及MIME参数详解
  • 原文地址:https://www.cnblogs.com/oeleven/p/10415906.html
Copyright © 2011-2022 走看看