1. 分公司不就是一部门吗?

B: 为一家在全国许多城市都有分销机构的大公司做办公管理系统,总部有人力资源部,财务,运营等。
B: 根据ID的不同区分。
A: 要求是树状结构,也就是组织结构,你倒好,搞成简单的平行结构。
A: 你有没有发现这种整体和部分的情况很多。
A: 人力资源部,财务部的管理功能可以复用于分公司。这其实就是整体和部分可以被一致对待的问题。
A: 总公司单做一棵树的根,那它的下属公司什么?
B: 是树的分支,各办事处的相关的职能部门由于没有分支了,所有可以理解为树叶。
A: 没有同一片叶子,但是同一颗树上的树叶的样子差不多。功能能复用到子公司,那么最好的办法就是,处理总公司还是子公司的财务管理功能的方法都是一样的。

2. 组合模式

将对象组合成树状结构以表示'部分-整体'的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

图1

class Program
{
    static void Main(string[] args)
    {
        Composite root = new Composite("root");
        root.Add(new Leaf("Leaf A"));
        root.Add(new Leaf("Leaf B"));

        Composite comp = new Composite("Composite X");
        comp.Add(new Leaf("Leaf XA"));
        comp.Add(new Leaf("Leaf XB"));

        root.Add(comp);

        Composite comp2 = new Composite("Composite XY");
        comp2.Add(new Leaf("Leaf XYA"));
        comp2.Add(new Leaf("Leaf XYB"));

        comp.Add(comp2);

        root.Add(new Leaf("Leaf C"));

        Leaf leaf = new Leaf("Leaf D");
        root.Add(leaf);
        root.Remove(leaf);

        root.Display(1);

        Console.Read();
    }
}

abstract class Component
{
    protected string name;

    public Component(string name)
    {
        this.name = name;
    }

    public abstract void Add(Component c);
    public abstract void Remove(Component c);
    public abstract void Display(int depth);
}

class Composite : Component
{
    private List<Component> children = new List<Component>();

    public Composite(string name)
        : base(name)
    { }

    public override void Add(Component c)
    {
        children.Add(c);
    }

    public override void Remove(Component c)
    {
        children.Remove(c);
    }

    public override void Display(int depth)
    {
        Console.WriteLine(new String('-', depth) + name);

        foreach (Component component in children)
        {
            component.Display(depth + 2);
        }
    }
}

class Leaf : Component
{
    public Leaf(string name)
        : base(name)
    { }

    public override void Add(Component c)
    {
        Console.WriteLine("Cannot add to a leaf");
    }

    public override void Remove(Component c)
    {
        Console.WriteLine("Cannot remove from a leaf");
    }

    public override void Display(int depth)
    {
        Console.WriteLine(new String('-', depth) + name);
    }
}

3. 透明方式与安全方式

A: 透明方式,也就是说在Component中声明所有用来管理对象的方法,其中包括Add,Remove等。这样实现Component接口的所有子类都具有Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的接口。但问题也很明显,因为叶子本身没有该功能,所有实现它没有意义。
A: 安全方式,就就是Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它。不过由于不够透明,所有树叶和树枝将不具有相同的接口,客服端的调用需要做相应的判断,带来不便。

4. 何时使用组合模式

A: 但你在需求中体现部分与整体层次(树状)的结构,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑组合模式了。

5. 公司管理系统

图2

class Program
{
    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);

        ConcreteCompany comp1 = new ConcreteCompany("南京办事处");
        comp1.Add(new HRDepartment("南京办事处人力资源部"));
        comp1.Add(new FinanceDepartment("南京办事处财务部"));
        comp.Add(comp1);

        ConcreteCompany comp2 = new ConcreteCompany("杭州办事处");
        comp2.Add(new HRDepartment("杭州办事处人力资源部"));
        comp2.Add(new FinanceDepartment("杭州办事处财务部"));
        comp.Add(comp2);


        Console.WriteLine("\n结构图:");

        root.Display(1);

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

        root.LineOfDuty();


        Console.Read();
    }
}

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();
        }
    }

}

//人力资源部
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);
    }
}

//财务部
class FinanceDepartment : Company
{
    public FinanceDepartment(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);
    }

}

6. 组合模式的好处

B: 组合模式定义了基本对象和组合对象类的层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象有可以被组合,这样不断的递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
B: 用户是不用关心到底是处理一个组合组件还是一个叶节点,也就用不着定义组合而写一些选择判断语句了。
A: 组合模式让客户可以一致地使用组合结构和单一个对象。


yuanoung
10 声望1 粉丝

« 上一篇
备忘录模式
下一篇 »
迭代器模式

引用和评论

0 条评论