• 设计模式之装饰者模式


    装饰者模式  Decorator

    什么是装饰者模式:动态将职责附加到对象上,若要扩展功能,装饰者提供了比继承更具弹性的代替方案。

    适用性:当采用类继承的方式会造成类爆炸的情况。如本文的例子中,基本饮料(被装饰者)可能有茶、水、牛奶等等、可以添加的(装饰者)有糖、果肉、珍珠等。

        如果通过继承的方式,为每一种类型的奶茶设计一种类会造成类爆炸,同时也不利于后期的扩展(如又添加一种基本饮料豆浆的情况),此时通过装饰者模式可以很好的解决问题。

        装饰者模式本质是一种组合的思想(不同于继承的思想),多组合少继承。利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。

    装饰者模式的主要组成部分:抽象被装饰者、具体被装饰者、抽象装饰者、具体装饰者。(当只有一个具体被装饰者、一个具体装饰者,其对应的抽象类可以省略)。

    装饰者模式类图:

    装饰者模式要点:

    1 多种具体被装饰者(主体类)抽象出一个抽象被装饰类,后面通过多态,动态传递具体对象。

    2 抽象装饰类继承抽象被装饰者(保持接口);要求传入被装饰者(使用父类应用、protected修饰);

    3 多种具体装饰者抽象出一个抽象装饰类。

    4 具体装饰者中,可以添加新方法,可以重写方法;需要使用被装饰者方法的地方用传入的被装饰者引用。

    装饰者模式的基本代码:

    /**
     * 被装饰抽象类——基本饮料
     *
     * 作用:当具体的被装饰类有多种时,抽象提出该抽象类,用于后面实现多态。
     */
    public abstract class BaseDrink {
        public abstract int calculate();
        public abstract void display();
    }
    /**
     * 具体的被装饰者类—— Water类
     * 继承抽象的被装饰者类,并实现其中的抽象方法。
     */
    
    public class Water extends BaseDrink{
        @Override
        public int calculate() {
            return 3;
        }
    
        @Override
        public void display() {
            System.out.println("water");
        }
    }
    /**
     * 具体的被装饰者类—— Tea类
     * 继承抽象的被装饰者类,并实现其中的抽象方法。
     */
    
    public class Tea extends BaseDrink{
        @Override
        public int calculate() {
            return 5;
        }
    
        @Override
        public void display() {
            System.out.println("Tea");
        }
    }
    /**
     * 抽象装饰者类——Decorator
     * 要点:1.抽象装饰者类中继承该抽象类以保持接口规范
     *      2.包含该抽象类的引用以通过多态的方式对多种被装饰者类进行装饰。
     */
    
    public abstract class Decorator extends BaseDrink{  //继承,保持接口
        protected BaseDrink bd;  //引用,多态
    
        public Decorator(BaseDrink bd) {
            this.bd = bd;
        }
    
        @Override
        public int calculate() {
            return bd.calculate();
        }
    
        @Override
        public void display() {
            bd.display();
        }
    }
    /**
     * 装饰者类  果肉
     */
    public class FleshDecorator extends Decorator{
        public FleshDecorator(BaseDrink bd) {
            super(bd);
        }
    
        @Override
        public int calculate() {
            return super.calculate() + 2;
        }
    
        @Override
        public void display() {
            super.display();
            System.out.println("+ flesh");
        }
    }


    /**
    * 装饰者类 糖
    */
    public class SugarDecorator extends Decorator{
    public SugarDecorator(BaseDrink bd) {
    super(bd);
    }

    @Override
    public int calculate() {
    return super.calculate()+1;
    }

    @Override
    public void display() {
    bd.display();
    System.out.println("+ sugar");
    }

    public void addMoreSugar(){
    System.out.println("add more sugar");
    }
    }
     
    /**
     * 测试用例
     */
    public class TestCase {
        public static void main(String[] args) {
            BaseDrink water = new Water();
            SugarDecorator sugarWater = new SugarDecorator(water);
            sugarWater.addMoreSugar();
            sugarWater.display();
            System.out.println(sugarWater.calculate());
            System.out.println("=========================");
            BaseDrink tea = new Tea();
            FleshDecorator fleshTea = new FleshDecorator(tea);
            fleshTea.display();
            System.out.println(fleshTea.calculate());
        }
    }
    //结果
    
    F:deaIC-2019.1.3-jbr11.winjre64injava.exe -javaagent:F:deaIC-2019.1.3-jbr11.winlibidea_rt.jar=7425:F:deaIC-2019.1.3-jbr11.winin -Dfile.encoding=UTF-8 -classpath E:eclipse-workspacedecoratorDemooutproductiondecoratorDemo TestCase
    add more sugar
    water
    + sugar
    4
    =========================
    Tea
    + flesh
    7
  • 相关阅读:
    _DataStructure_C_Impl:图的邻接矩阵存储
    ios的单元測试OCUnit以及更新了之后的XCTestCase
    java之 ------ 可变參数和卫条件
    【能力提升】SQL Server常见问题介绍及高速解决建议
    NYOJ 116 士兵杀敌 (线段树,区间和)
    Spring和MyBatis环境整合
    TypeScript和JavaScript的一些小技巧记录
    VSCode配置TypeScript
    function 与 => 的区别
    Egret里用矢量挖圆形的洞
  • 原文地址:https://www.cnblogs.com/youzoulalala/p/11046607.html
Copyright © 2020-2023  润新知