zoukankan      html  css  js  c++  java
  • 装饰模式 Kevin

    4.1、装饰模式的特点

      装饰模式:装饰模式主要是解决了,我们以动态的,透明的形式为某个类型添加一个新的职责,客户程序可以不知道我们具体添加的功能职责,而客户程序只是根据对象提供的方法进行调用即可。而具体职责操作留给装饰对象去完成。

      我们这里给出装饰模式的经典模式的类图:      C#设计模式之装饰设计模式(Decorator)

      我们这里对这个经典结构进行稍微的说明:我们这里结合我们上面的播放器来说

      1、对于Compnent,我们定义一个IPlayer这样的接口,我们接口中定义方法,Play()方法。

      2、然后我们把要装饰这个播放器的装饰类型进行抽象,抽象出接口IDecorator接口。这个即可继承自IPlayer接口。

      3、接着,我们定义一个简单的播放器对象,实现这个IPlayer接口。

      4、我们实现播放音乐和视频文件的装饰类型的实现。

      5、我们将简单的播放器对象,通过装饰对象进行装饰,为这个简单播放器套上一层一层的外壳,使其具有播放音乐和视频的功能。

      4.2、装饰模式的使用场景

      1、当我们需要为某个现有的对象,动态的增加一个新的功能或职责时,可以考虑使用装饰模式。

      2、适应于某个对象的职责经常发生变化或者经常需要动态的增加职责,避免因为这种为了适应这样的变化,而增加继承子类扩展的方式,因为这种方式为 造成,子类膨胀的速度过快,难以控制。

      五、装饰模式的经典实现

      经过上面的简单描述,我想大家很想知道装饰模式的经典实现方案吧!我们来结合播放器的实例来分析实现,下面给出核心代码:

    ///<summary>/// 简单播放器的统一接口 ///</summary>publicinterface IPlayer { void Play(); }
    ///<summary>/// 播放器的普通实现类 ///</summary>publicclass Player : IPlayer { #region IPlayer 成员
    publicvoid Play() { thrownew NotImplementedException(); }
    #endregion }
    // <summary> // 装饰器接口 // </summary>publicinterface IDecorator : IPlayer
    ///<summary>/// 装饰器的抽象基类 ///</summary>publicabstractclass DecoratorBase : IDecorator { protected IPlayer play =null; public DecoratorBase(IPlayer player) { this.play = player; }
    #region IPlayer 成员
    publicabstractvoid Play();
    #endregion }
    ///<summary>/// 音乐播放器装饰器 ///</summary>publicclass MusicDecorator : DecoratorBase { public MusicDecorator(IPlayer play) : base(play) { } publicoverridevoid Play() { thrownew NotImplementedException(); } }
    ///<summary>/// 视频播放器装饰类 ///</summary>publicclass VedioDecorator : DecoratorBase { public VedioDecorator(IPlayer play) : base(play) { } publicoverridevoid Play() { thrownew NotImplementedException(); } }

      具体的测试调用代码如下:

    staticvoid Main(string[] args) { IPlayer play =new Player(); play =new MusicDecorator(play); play =new VedioDecorator(play); }

      经过了2次的装饰后,该播放器对象,可以播放任何格式的文件。通过上面的过程,我们发现了我们在使用装饰模式的时候,有如下几点我们需要把我好:

      1、我们在开发的过程中,如果需要为某个类型添加多个职责的时候,我们需要多个装饰实现类,这样类太多的时候,我们需要将这个对象装饰多次。

      2、我们对我们的装饰过的对象,如何指定的撤销某个装饰过程的状态呢?类似我们使用某些应用程序中的undo操作。

      3、对于动态装饰的对象,我们debug的时候,我们很难跟踪和调试。

      六、装饰模式的其他方案

      装饰模式的具体过程如下:      image

      一、通过配置文件来完成装饰操作

      具体的操作过程如下:配置文件中配置对象要完成的装饰步骤,通过公共的配置读取类,通过字典缓存装饰的步骤,然后传入普通的对象,返回装饰后的对象。

    image

      我们这里给出配置文件的格式:

    <?xml version="1.0" encoding="utf-8" ?><Decorator><Section><Class name="" type=""><Step name="" type=""/><Step name="" type=""/><Step name="" type=""/></Class><Class name="" type=""><Step name="" type=""/><Step name="" type=""/><Step name="" type=""/></Class><Class name="" type=""><Step name="" type=""/><Step name="" type=""/><Step name="" type=""/></Class></Section></Decorator>

      我们来看具体的装饰器步骤构造器代码:

    publicclass DecoratorFactory { publicstatic T BuilderPlay<T>(T play) { Dictionary<Type, List<IDecorator>> steps =new Dictionary<Type, List<IDecorator>>(); List<IDecorator> list = steps[typeof(T)];
    foreach (IDecorator item in list) { play = (T)Activator.CreateInstance(item.GetType(), play); }
    return play; } }

      二、通过特性+反射的形式来组织装饰的过程image   这里就不给出具体的实现代码了,下篇或者后续给出分析几类基于特性+标记的实现方案。大伙也可以提出其他的不同实现思路。

      七、装饰模式使用总结

      通过上面的讲述,我们知道装饰模式,特别适合对某个类型的对象,动态的增加新的职责,应用程序就像使用原来的对象一样使用对象新增的装饰后的功能,装饰模式就好像是穿了一层层的外壳,这样的方式避免了通过继承来为类型添加新的职责的形式可取,通过继承的方式容易造成子类的膨胀,但是当装饰类太多的时候,也是个难以维护的问题,至少是在装饰对象的时候,我们可能需要多步操作来完成对象的装饰,这时候我们可以同上面提出的改进的方案,来完成自动配置装饰模式,记录操作模式的状态,可以进行有效的回滚操作,以完成撤销操作

  • 相关阅读:
    表数据文件DBF的读取和写入操作
    【转】Hive SQL的编译过程
    Hadoop配置机架感知
    pssh安装和使用
    hive12启动报错org.apache.thrift.server.TThreadPoolServer.<init>(Lorg/apache/thrift/server/TThreadPoolServer$Args;)
    【转】Oozie4.2.0配置安装实战
    【转】别因为要学的太多反而压垮自己
    【转】hadoop2.6 配置lzo压缩
    hive 启动 Specified key was too long; max key length is 767 bytes解决办法
    【转】linux configure报错configure: error: C++ preprocessor “/lib/cpp” fails sanity 的解决办法
  • 原文地址:https://www.cnblogs.com/kfx2007/p/2793338.html
Copyright © 2011-2022 走看看