zoukankan      html  css  js  c++  java
  • 【装饰者模式】Decorator Pattern

    装饰者模式,这个模式说我一直记忆深刻的模式,因为Java的IO,我以前总觉得Java的IO是一个类爆炸,自从明白了装饰者模式,Java的IO体系让我觉得非常的可爱,我们现在看看什么是装饰者,然后再来看如何去很爽的运用Java的IO(C#的IO则不同)  

    Component:这个是抽象接口(这里的接口的意思不是interface关键字对应的接口,而是一个对应的口),以规范准备接收附加责任的对象。

    Concrete Component:具体的组件,这个可以接收附加责任(装饰)的类

    Decorator:装饰的抽象接口,实现一个与抽象构件接口一致的接口。

    ConcreteDecorator:具体装饰类,负责给具体组件加上装饰的。

    (每次想这个,我都觉得好抽象,不管那么多,了解一下就好,先看例子再回来看)

    我们直接来弄一个,软饮(吃,这个东西最好做这个模式了)。

    我们有[软饮]是一个抽象存在的东西,所以肯定是我们的抽象组件

    public abstract class BeverageComponent
        {
    
            public abstract string GetDescription();
    
            public abstract double Cost();
        }

    有了抽象组建,我们来想想有那些具体的组建,咖啡(Espresso),House Blend(星巴克的首选咖啡,我喜欢,大家可以试试)

    我们来建立这两个类:

     public class Espresso : BeverageComponent
        {
            public override string GetDescription()
            {
                return "Espresso";
            }
    
            public override double Cost()
            {
                return 12;
            }
        }
    
        public class HouseBlend : BeverageComponent
        {
            public override string GetDescription()
            {
                return "HouseBlend";
            }
    
            public override double Cost()
            {
                return 15;
            }
        }

    我们为descrption字段赋值上组建的名字,然后实现了抽象方法Cost,返回自己的价格。

    到这里我们拥有了抽象组建和具体组建,我们现在来构建一下抽象装饰类

    public abstract class BeverageDecorator : BeverageComponent
        {
      //类里面虽然什么都没有,但是我们可以在这里添加一些专门属于装饰类的抽象方法. }

    我们从UML图上面看还是继承了抽象组件,有了抽象的装饰类,我们来构建一下具体的装饰类

     public class Milk : BeverageDecorator
        {
            private BeverageComponent _beverage;
            public Milk(BeverageComponent beverage)
            {
                _beverage = beverage;
            }
            public override string GetDescription()
            {
                return _beverage.GetDescription() + "+Milk";
            }
    
            public override double Cost()
            {
                return _beverage.Cost() + 5;
            }
        }
    
        public class Sugar : BeverageDecorator
        {
            private BeverageComponent _beverage;
            public Sugar(BeverageComponent beverage)
            {
                _beverage = beverage;
            }
            public override string GetDescription()
            {
                return _beverage.GetDescription() + "+Sugar";
            }
    
            public override double Cost()
            {
                return _beverage.Cost() + 2;
            }
        }

    我们构建了Sugar和Milk两个装饰类,里面带有一个又参构造并要求传入抽象组件的对象,这里说装饰者模式的核心,为什么要求传入一个抽象组件的对象呢?

    这里可以传入具体组件的对象和装饰类的对象,而且当你传入了具体组件以后就不能够继续传入其他的装饰和组件了。关键的地方!!!

    我们也就是可以认为,具体组件要做的是功能或者主要的东西,装饰的东西对于具体组件是可有可无的,是用于做辅助的。我们来看看一杯加糖的牛奶的咖啡怎么来。

    class Program
        {
            static void Main(string[] args)
            {
                var beveage = new Milk(new Sugar(new Espresso()));
    
                Console.WriteLine("Descripiton:" + beveage.GetDescription());
                Console.WriteLine("Cost:" + beveage.Cost());
    
                Console.ReadLine();
            }
        }

    我们先创建一个牛奶对象,在传入糖,最后把我们要的实物写进去,来看下输出。
    输出为:


     到这里,装饰者模式就结束了。

    我们来谈谈它的应用场景:

      如果你有许多的功能,并且有许多的辅助功能去辅助你这些具体功能,可以用装饰者模式。

    优点:

      

      1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
      2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
     

    缺点:

      1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
      2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
      3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然  也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

    Java的IO

      

    这张图说JAVA的API,我们的Component说InputStream. 除了我用红笔圈出来的都说具体组建。我们走到FilterInputStream里面看看

    继承了FilterInputStream的所有类都是装饰类,所以FilterInputStream是抽象装饰类。

    也就是说继承FilterInputStream这些类主要说为了辅助那些直接继承了InputStream的具体组件类(Reader,Writer,OutputStream都说这样的)

    我们现在知道怎么用了把

    Stream stream=new BufferedInputStream(new FileInputStream()); 这样我们主要功能说读文件,只不过在这个基础上面加了一层缓存。如果你要其他的辅助可以直接加进去,是不是很方便。

  • 相关阅读:
    卸载IE
    js判断是否是object、array
    正则表达式中/i,/g,/ig,/gi,/m的区别和含义
    谷歌地图控制圆圈随缩放自适应大小 js
    WGS84坐标转换GCJ02坐标 JS实现
    Google图片和NASA 网站图片的爬虫
    Yolov_3 网络结构分析
    启动Tensorboard时发生错误:class BeholderHook(tf.estimator.SessionRunHook): AttributeError: module 'tensorflow.python.estimator.estimator_lib' has no attribute 'SessionRunHook'
    MyBatis -- generator 逆向工程
    bat使用方法汇总
  • 原文地址:https://www.cnblogs.com/guochenkai/p/3898082.html
Copyright © 2011-2022 走看看