大话设计-组合模式

【概念介绍】

1.定义:组合模式是将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

2.如图所示:

        

Component是一个抽象类,在其下面定义所有子类用到的事件、方法;它也可作为对象声明的接口,声明接口用于访问和管理其子部件。而Composite和Leaf可以作为具体类,换句话说,也叫做具体对象(部分),作为部分,可以不必全部继承父类所有的方法事件。这个“部分”可以理解为大树的枝干也可以理解为是大树的叶子。当然,大树会有若干枝干,但是叶子却是大树上最小的不可再分的。但是,为了使得客户端判别事件的简便性,于是,定义了统一的接口。在这里大鸟提到了“透明方式和安全方式”:前者是说,让叶节点对于外界没有区别,它们具备完全一致的行为接口,但是也会存在叶节点不具备某些方法功能的现象,所以存在无意义的方法;后者是说,各个分支都具备实现自己功能的方法,没有多余的方法,此时,树叶和树枝不具有相同的接口,客户端调用需要做相应的判断,这样就会增加工作负荷,带来很大的不便。所以说,还是透明方式和组合模式是一家子啊。

【个人理解】

刚一开始看组合模式前面那个例子:小菜给公司设计那个公司管理模式的时候,我给理解偏了,总公司下面既有分公司也有财务部、人力资源部等,我当时想的是总公司和分公司都是一样的啊,都是公司,日常管理都是一样的啊,在这里哪里体现整体和部分的关系了???要是说财务部啦、人力资源部啦这个和总公司可以说是整体、部分的关系…还是学习的时候不仔细,没有看透组合模式,或许是看大话设计这本书看的太久了,竟然有了和小菜同样的经历,但是没有人家那么高大上,人家做梦梦到超模大赛,将二十三个设计模式外加简单工厂模式演绎的淋漓尽致,我就是中午休憩了一下,梦到了组合模式,下午,竟然想通了…

其实,结合透明方式就不难理解啦,需求中体现部分整体层次的结构时,用户忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象,这个时候组合模式就可以派上用场啦。

【组合模式的好处】

1.组合模式定义了包含基本对象、组合对象的类的层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。

2.用户是不关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些判断语句了。

【活学活用】

了解了组合模式还不够,更重要的是能把所学运用到实际当中,拿书中的例子来说:总公司和各个分公司及总公司下面的财务部、人事部门等。各个分公司可以看作是枝节点可以再细分,财务部等就是叶节点不可以再分。运用组合模式的思想:总公司作为整体可以抽象出一个类来,分公司们(具有相同的方法事件)抽象成一个类,财务部们等也可以抽象出一个类来,它们共同继承总公司这个抽象类的属性、事件、方法,先看一下具体的类图:


也许你会奇怪,公司的下属部门可能不具备Company的所有功能或者是执行事件的具体形式不同,但是我们为了减轻客户端不必要的负荷,可以遵照透明方式的原则进行这样的设计,体现了编码的灵活性。

看到这张类图我们可以很轻松的写出代码来,先看下面是先对各个类进行的定义:

 //公司类 抽象类(接口)
    abstract class Company
    {
        protected string name;

        public Company(string name)
        {
            this.name = name;
        }
        public abstract void Add(Company c);
        public abstract void Remove(Company c);
        public abstract void Display(int depth);
        public abstract void LineOfDuty();//每个部门或公司会执行不同的职责,在这里只是抽象出来了“履行职责”这个方法,接下来就是具体问题具体分析了。
    }

//定义各个具体公司类
    class ConcreteCompany : Company
    {
        private List<Company> children = new List<Company>();
        public ConcreteCompany(string name)
            : base(name)
        { 
        }
        public override void Add(Company c)
        {
            children .Add (c);
        }
        public override void Remove(Company c)
        {
            children .Remove (c);
        }
        public override void Display(int depth)
        {
            Console .WriteLine (new String ('-',depth )+name);
            foreach (Company component in children)
            {
                component.Display(depth + 2);
            }
        }
        public override void LineOfDuty()
        {
            foreach (Company component in children)
            {
                component.LineOfDuty();
            }
        }
    }

  //定义各个部门类,继承Company类
    class HRDepartment : Company
    {
        public HRDepartment(string name)
            : base(name)
        { }
        public override void Add(Company c)
        {
        }
        public override void Remove(Company c)
        {
        }
        public override void Display(int depth)
        {
            Console.WriteLine(new String('-', depth) + name);
        }
        public override void LineOfDuty()
        {
            Console .WriteLine ("{0} 员工招聘培训管理",name );
        }
    }

按照一定的条理把这些类都写好之后,就是处理客户端代码了,需要注意的是:一定不要忘了去实例化,然后再根据具体的逻辑关系进行编码,如下图是我们想要得到的效果

                                     

客户端代码如下:

static void Main(string[] args)
        {
            ConcreteCompany root = new ConcreteCompany("加菲猫总公司");
            root.Add(new HRDepartment("总公司人力资源部"));
            root.Add(new FinanceDepartment("总公司财务部"));

            ConcreteCompany comp = new ConcreteCompany("意大利面分公司");
            comp.Add(new HRDepartment("分公司人力资源部"));
            comp.Add(new FinanceDepartment("分公司财务部"));
            root.Add(comp);
<span style="white-space:pre">	</span>    Console.WriteLine("\n结构图:");
            root.Display(1);

            Console.WriteLine("\n职责:");
            root.LineOfDuty();

            Console.Read();
}
【小结】

总感觉每个设计模式都有着相一致的套路,可能是设计模式学的久了,学多了,把概念弄混了吧:完全贯彻面向对象的思想,尽可能多的体现六大设计原则,尽可能的抽象出类来,尽量减少耦合性,无时无刻不再向着OO精神:可维护、可扩展、可复用、灵活性好这方面靠拢。没错啊,编程是一门技术,更是一门艺术。

posted @ 2014-11-24 15:07  幻想泡沫  阅读(164)  评论(0编辑  收藏  举报