Composite 模式和其他(2) - 抽象什么

    /// <summary>
    /// PS: 在写这个文章时想用的标题是 Composite 模式和其他模式,后来感觉想写的不只是其他模式的关系
    /// 就写了这个标题,好象语法不通,但没办法,从中学开始语文考试就没超过60分^-^
    /// </summary>
    当使用抽象类的时候我们可以先定义一个 Component 抽象类
, 在类里加了两个重载的方法 IsTree
用于判断合成对象是否的树结构.
    public abstract class Component
    {
            private string _strName = string.Empty;
            private Component _parent; // 父对象

            public Component(string name)
            {
                  this._strName = name;
            }
            public string Name{get {return this._strName;}}
            public Component Parent{get{return this._parent;}}
            public bool IsTree()
            {
                   return this.IsTree(new Hashtable());
            }
            public abstract bool IsTree(Hashtable visited);

    }
    在 Composite 类和 Leaf 类里实现  IsTree 方法都很简单,只要检查 Coomposite 对象的 Name 是否在访问的哈希表中出现过,并且要检查 COmposite 对象的子对象是否是树结构
    public class Composite : Component
    { 
           private IList _listChild;
           public Composite(string name):base(name){}
 
           public IList ChildComponentItems
           {
                  get{return this._listChild;}
           }

           public override bool IsTree(Hashtable visited)
          {
            visited.Add(this.Name, this);
            foreach (Component dc in this.ChildComponentItems)
            {
                if (visited.Contains(dc.Name) || !dc.IsTree(visited))
                {
                    return false;
                }
            }
            return true;
        }

    } 
    在 Leaf 类里就更简单了,因为 Leaf 对象本身肯定是树结构,只要在访问的哈希表中记录 Leaf 对象的 Name 就可以了
    public class Leaf : Component
    {
            public Leaf(string name):base(name){}
            
            public override bool IsTree(Hashtable visited)
            {
                  visited.Add(this.Name, this);
                  return true;
            }

    }
    现在.我们的合成模式可以判断是否是树结构了.
    现在我们终于能开始考虑第二个思想了(是思想不是法律!!!,不实现不违法!)
    他让我们把合成对象和叶对象的操作提供一个统一的接口或抽象,苍天哪!
    在 Composite 模式中有几个常用的操作 
        public bool Contains(string name);
        public Component Find(string name);
        public int GetDeviceCount();
    实现了这些操作或方法后,我们就要对合成对象和叶对象进行抽象了,具体怎么抽象,抽象什么和我们的合成对象的应用有关. 
    第一次应用 Composite 模式是在做工业控制项目中用于设备管理.在设备管理中要求实现设备树.其中节点就是合成对象,他可以添加设备或其他的节点,设备就是叶(在实际中,还有总线设备,他也可以添加设备,为了讨论方便,这里就把他排除在外).
    OK,现在就对这些节点和设备抽象了.

    首先看抽象什么,在对设备来说有一些常规操作比如 连接断开设备,打开关闭设备和读写设备等.这些我们可以把他抽象到顶层抽象类 Component 中.在 Leaf 类里实现这些抽象方法是直接操作设备,在节点里是通过迭代操作节点里的所有设备
    这样我可以对节点和设备使用同一个抽象来操作,比如我们可以选择打开一个设备,也可以打开一个节点下的所有设备.两种操作对使用合成对象的客户代码是一样的.
    可有些对设备的操作比较特殊,不适合在节点里对成批的设备同时操作(这种情况在其他的合成对象也会遇到),这些方法需要抽象到 Component 类里吗? 郁闷第二次.如果把这些操作都抽象到 Component 类里,Component 类会不会很变态?

    同时,现实中设备千差万别,我们怎么对这些设备进行抽象.或者说,我们要把 Leaf 作为其他设备类的顶层抽象.那 Leaf 要有那些功能.怎么把各种设备的操作抽象到 Leaf 中,还有怎么根据设备的主要特性设定设备子类的继承关系,比如我们可以根据设备的连接形式来确定设备子类的继承关系
    比如对于板卡类的设备,我可以定义一个类继承 Leaf 类
    public class CardDevice : Leaf
    {
          ......
    }
    在这个类里,我们会实现板卡通讯的基本功能
    同时对于 RS323(串口)连接的设备,我们可以定义一个类,同样继承 Leaf  类
    public class RS232Device : Leaf
    {
          .......
    }
    在 RS232Device 类里我们实现了和 RS232 口通讯的基本功能,
    这样我们在扩充设备时,如果设备是用板卡的就可以继承 CardDevice 类,同样如果设备使用 RS232 口就可以继承 RS232Device 类. 很好的解决方案,不是吗?
    确实不是!
    假如我们板卡和串口的通讯方式都有了新的版本,为了实现新的版本我们重新定义两个类来扩充新的协议,
    public class CardDevice2 : CardDevice 
    {
          ......
    }
    public class RS232Device2 : RS232Device 
    {
          .......
    }

    假如板卡的扩充和串口的扩充都增加了一个相同的控制方式,比如都可以用很通用命令让设备说 "Hello World",很夸张.哈哈.那这个方式在以前的版本实现不了,那么我们就要在 CardDevice2 和 RS232Device 类都要实现,并且两个类里的代码几乎是一致的,那么代码重用在这里只能表现为粘贴和复制了.
    幸好还个 桥接(Bridge)模式,他的广告词是: 将抽象部分与实现部分分离,使它们都可以独立的变化.
    好象我们能用来解决这个问题.买东西不能看广告,要看疗效.究竟 Bridge 模式能解决我们的问题吗? 谁用谁知道.哈哈.
   

你可能感兴趣的:(com)