zoukankan      html  css  js  c++  java
  • java设计模式-装饰器模式

    1.装饰器(Decorator)模式的定义

    • 指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

    2.装饰器模式的主要优缺点

    优点:

    • 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
    • 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。

    缺点:

    • 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。

    3. 装饰器模式的主要角色

    • 抽象组件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。
    • 具体组件(Concrete    Component)角色:实现抽象构件,通过装饰角色为其添加一些职责。
    • 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
    • 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。

    从类图上看,装饰器模式与代理模式很像,是它们的目的不同,所以使用方法和适用场景上也就不同 ,装饰器模式与代理模式的区别:

    • 代理模式专注于对被代理对象的访问。
    • 装饰器模式专注于对被装饰对象附加额外功能。

    4.装饰器的结构图

     5.装饰器的实现,以coffee为例

    •  创建抽象组件类
    package com.lw.designpattern.decorate;
    
    /**
     * @Classname Coffee
     * @Description 抽象组件类,咖啡
     * @Author lw
     * @Date 2020-01-13 09:01
     */
    public interface Coffee {
    
        /**
         * 价格
         *
         * @return double
         */
        double price();
    
        /**
         * 配料
         *
         * @return String
         */
        String ingredients();
    }
    • 创建具体组件类
    package com.lw.designpattern.decorate;
    
    /**
     * @Classname SimpleCoffee
     * @Description 具体组件类,原味coffee
     * @Author lw
     * @Date 2020-01-13 09:02
     */
    public class SimpleCoffee implements Coffee {
    
        @Override
        public double price() {
            return 1;
        }
    
        @Override
        public String ingredients() {
            return "coffee";
        }
    }
    • 创建抽象装饰类
    package com.lw.designpattern.decorate;
    
    /**
     * @Classname AbstractCoffeeDecorator
     * @Description 抽象装饰类,咖啡的"装饰器"
     * @Author lw
     * @Date 2020-01-13 09:04
     */
    public abstract class AbstractCoffeeDecorator implements Coffee {
    
        protected Coffee coffee;
    
        public AbstractCoffeeDecorator(Coffee coffee) {
            this.coffee = coffee;
        }
    
        /**
         * 价格
         *
         * @return double
         */
        @Override
        public double price() {
            return coffee.price();
        }
    
        /**
         * 配料
         *
         * @return String
         */
        @Override
        public String ingredients() {
            return coffee.ingredients();
        }
    }
    • 创建具体装饰类,牛奶
    package com.lw.designpattern.decorate;
    
    /**
     * @Classname WithMilk
     * @Description 具体装饰类,牛奶
     * @Author lw
     * @Date 2020-01-13 09:10
     */
    public class WithMilk extends AbstractCoffeeDecorator {
    
        public WithMilk(Coffee house) {
            super(house);
        }
    
        /**
         * 价格
         *
         * @return double
         */
        @Override
        public double price() {
            double addPrice = 1;
            return super.price() + addPrice;
        }
    
        /**
         * 配料
         *
         * @return String
         */
        @Override
        public String ingredients() {
            String addIngredients = "milk";
            return super.ingredients() + "," + addIngredients;
        }
    }
    • 再创建一个具体装饰类,糖
    package com.lw.designpattern.decorate;
    
    /**
     * @Classname WithSugar
     * @Description 具体装饰类,糖
     * @Author lw
     * @Date 2020-01-13 09:10
     */
    public class WithSugar extends AbstractCoffeeDecorator {
    
        public WithSugar(Coffee house) {
            super(house);
        }
    
        /**
         * 价格
         *
         * @return double
         */
        @Override
        public double price() {
            double addPrice = 0.5;
            return super.price() + addPrice;
        }
    
        /**
         * 配料
         *
         * @return String
         */
        @Override
        public String ingredients() {
            String addIngredients = "sugar";
            return super.ingredients() + ","  + addIngredients;
        }
    }
    • 单元测试
      /**
         * 装饰者模式
         */
        @Test
        public void testDecorate() {
            // 原味咖啡
            Coffee c = new SimpleCoffee();
            System.out.println("花费了: " + c.price());
            System.out.println("配料: " + c.ingredients());
            System.out.println("============");
    
            // 增加牛奶的咖啡
            c = new WithMilk(c);
            System.out.println("花费了: " + c.price());
            System.out.println("配料: " + c.ingredients());
            System.out.println("============");
    
            // 增加糖的咖啡
            c = new WithSugar(c);
            System.out.println("花费了: " + c.price());
            System.out.println("配料: " + c.ingredients());
            System.out.println("============");
        }

    打印结果

     6.装饰器的适用场景

    • 运行时,你需要动态地为对象增加额外职责时。
    • 当你需要一个能够代替子类的类,借助它提供额外方法时。

    7.装饰器的扩展

    • Java提供的工具包中,IO相关工具就普遍大量使用了装饰器模式,例如充当装饰功能的IO类如BufferedInputStream等,又被称为高级流,通常将基本流作为高级流构造器的参数传入,将其作为高级流的一个关联对象,从而对其功能进行扩展和装饰。
    • 用BufferedInputStream和用FileInputStream去read一个文件实际使用方式上是一样的,能用FileInputStream.read(),就能用BufferedInputStream.read(),只不过,BufferedInputStream把FileInputStream包装了一下,增加了一个缓存,并不控制底层FileInputStream的read()行为。
  • 相关阅读:
    netcore 发布到IIS上常见错误
    mysql解压文件安装
    VS2017 怎么启用nuget程序包还原?
    vue-qr生成下载二维码
    控制器,action, 过滤器, 权限
    WebSocket浅析(一):实现群聊功能
    BOM元素之window对象
    arguments及arguments.callee
    Spring入门6事务管理2 基于Annotation方式的声明式事务管理机制
    Spring入门5.事务管理机制
  • 原文地址:https://www.cnblogs.com/lwcode6/p/12185620.html
Copyright © 2011-2022 走看看