1

我目前遇到了一个设计问题。

假设有一个组件层次结构。这些组件中的每一个都派生自一个Component看起来像这样的抽象类型:

public abstract class Component
{
    public abstract Component Parent { get; }
    public abstract ComponentCollection Children { get; }
}

现在我想为这些组件添加一些可选功能,让我们以能够在组件层次结构中搜索并在层次结构中选择组件为例。

像这样在基类中提供这些可选功能是否被认为是不好的做法:

public abstract class Component
{
    // Other members

    public abstract bool IsSearchable { get; }
    public abstract bool Search(string searchTerm);

    public abstract bool IsSelectable { get; }
    public abstract bool Select();
}

而“搜索能力”和“选择能力”是通过例如使用策略模式在派生组件中管理的?

不知何故,这对我来说似乎违反了 SRP,但在我看来,唯一的选择是为每个可选功能提供一个接口,并且只在支持此功能的组件上实现它。

在我看来,这将有一个缺点,即每次我想检查组件是否提供特定功能时,我都必须编写这样的代码:

public bool Search(Component component, string searchTerm)
{
    ISearchable searchable = component as ISearchable;
    if(searchable != null)
    {
        searchable.Search(searchTerm);
    }
}

您会选择哪种策略,或者您有什么更好的想法?

提前致谢!

4

3 回答 3

1

一个可能的选择:

如您所说,如果通过策略模式(依赖注入)提供可搜索性/可选择性实现,那么我认为 ISearchable 和 ISelectable 的接口是一个更好的主意。

您可以从这些接口派生出您的策略对象,并在您的基组件类中为它们实现 getter - GetSearchable()、GetSelectable() - 其中 Component 中的默认实现返回 null(或者如果您使用接口的无操作实现不喜欢空)。

于 2011-06-15T09:29:02.653 回答
0

为什么不用装饰器?

Component c = new Component ();
var selectableAndSearchableOne = new SelectableComponent (new SearchableComponent (c));
于 2011-06-16T21:36:47.780 回答
0

好的另一个:这次你也知道了组件的扩展点。像访客一样的图案

public interface IHasExtensions
    {
        List<Extension> Extensions { get; }
        void Extend (Extension ext);
    }

    public class Component : IHasExtensions
    {
        List<Extension> exts = new List<Extension> ();

        public List<Extension> Extensions
        {
            get { return exts; }
        }

        public void Extend (Extension ext)
        {
            exts.Add (ext);
        }

        void Draw() { }
    }

    public abstract class Extension
    {
        readonly protected Component _Component;

        public Extension(Component component)
        {
            _Component = component;
        }
    }

    public class SearchExtension : Extension
    {
        public SearchExtension (Component component) : base (component)
        {

        }
    }

    public class SelectionExtension : Extension
    {
        public SelectionExtension (Component component) : base (component)
        {

        }
    }

    public class test_fly
    {
        void start ()
        {
            Component c = new Component ();
            c.Extend (new SearchExtension (c));
            c.Extend (new SelectionExtension (c));

            var exts = c.Extensions; // I Know the extensions now
        }
    }
于 2011-06-18T22:30:08.883 回答