【问题标题】:Composite Pattern Simplified复合模式简化
【发布时间】:2016-02-12 14:06:15
【问题描述】:

如果不实现组件并将所有内容都视为组合,我会失去什么?

我已经放弃了叶子节点的实现:

class Component : IComponent
{ 
    /*...*/ 
}

现在请看一下我的代码。

public interface IComponent
{
    int ID { get;set; }
    string Name { get;set;}
    void Add(IComponent item);
    void Remove(IComponent item);
    List<IComponent> Items { get; }
    void Show();        
}


public class Composite : IComponent
{
    private int _id;
    public int ID
    {
        get { return _id; }
        set { _id = value; }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public Composite(int id, string name)
    {
        _id = id;
        _name = name;
    }

    private List<IComponent> _items = new List<IComponent>();

    public void Add(IComponent item)
    {
        _items.Add(item);
    }

    public void Remove(IComponent item)
    {
        _items.Remove(item);
    }

    public List<IComponent> Items
    {
        get
        {
            return new List<IComponent>(_items);
        }
    }

    public void Show()
    {
        Console.WriteLine("ID=" + _id + "; Name=" + _name);
    }        
}


class Program
{
    static void Main(string[] args)
    {
        IComponent root = new Composite(1, "World");

        IComponent asia = new Composite(2, "Asia");
        IComponent europe = new Composite(3, "Europe");

        root.Add(asia);
        root.Add(europe);

        asia.Add(new Composite(4, "China"));
        asia.Add(new Composite(5, "Japan"));

        europe.Add(new Composite(6, "Germany"));
        europe.Add(new Composite(7, "Russia"));

        root.Show();
        Program.Traverse(root.Items);

        Console.ReadLine();
    }

    static void Traverse(List<IComponent> items)
    {            
        foreach (IComponent c in items)
        {
            c.Show();

            Traverse(c.Items);
        }
    }
}

这种复合模式的方法有什么问题?这种设计会遇到什么样的问题?

【问题讨论】:

  • 您可能会考虑澄清您的问题是“如果不实现组件并将所有内容都视为复合材料,我会失去什么”......我最初认为您的代码有问题,并意识到您的问题不是关于“有效”的代码,而是为什么要添加 Leaf :)
  • 建议你在这里学习代码示例和内容:dofactory.com/patterns/patterncomposite.aspx 看不出有什么理由应该“放弃叶子节点的实现”。祝你好运!

标签: c# composite


【解决方案1】:

您正在放弃任何对“叶子”进行子类化的机会,如果事实证明您有不同类型的“节点”,您最终可能会以一种或另一种方式污染结构。而且你也违反了单一责任原则。使用复合模式非常很容易受到各种污染,我认为干净利落总是值得的。

【讨论】:

  • “污染”是什么意思?能说清楚一点吗?
  • 对我来说,您似乎没有将树结构与树数据分开。复合是一种非常危险的设计模式,因为它倾向于引诱您将所有内容放入树和节点中,甚至是很多不应该存在的东西。它既漂亮又优雅,但如果您将太多不同类型的逻辑/信息放入同一个视图中,也会变得混乱。每次向树中添加特殊情况时,都会发生“污染”。
【解决方案2】:

如果我理解正确的话,不是复合模式的叶节点的概念。

任何没有子节点的节点都会自动成为叶节点。
查看您的代码,这不是必需的

private List<IComponent> _items = new List<IComponent>();

    public void Add(IComponent item)
    {
        _items.Add(item);
    }

    public void Remove(IComponent item)
    {
        _items.Remove(item);
    }

    public List<IComponent> Items
    {
        get
        {
                return new List<IComponent>(_items);
        }
    }

我正在查看ControlCollection 类,它是Control 类的属性。

虽然不完全是复合模式,但每个 Control 都知道它是谁的孩子,而这在您的代码中是缺失的。

我的理解可能完全错误。高手可以指正:)

编辑:我查看了 dofactory 参考,它似乎有复合模式中叶类的概念。我完全不理解的错误。

但我建议您通过 ControlControlCollection 和相关类查看 .net 实现某种复合模式的方式。

EDIT2:如果要删除上面的代码,您将拥有另一个类,它是IComponent 的集合,您可以使用属性IList&lt;IComponent&gt; 公开它,而该属性又将具有add/ 的方法remove.

EDIT3:.net 不限制用户在上述类层次结构中添加子控件。如果您想限制某人定义叶节点(没有任何子节点的节点)的能力,您可以使用 dofactory 设计方式。

EDIT4:dofactory 代码显示的方式,您必须定义一个叶节点,它将为 Add/`Remove' 抛出 NotImplementedException

【讨论】:

  • 如果我放弃这个代码段,我将如何存储孩子?那应该是什么机制呢?
  • 好的。那么 IComponent-interface 会发生什么?实施将不再有意义。这反过来又使整个设计变得毫无意义。
猜你喜欢
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
相关资源
最近更新 更多