可选组件功能vs SRP

问题描述

| 我目前遇到一个设计问题。 假设有一个组件层次结构。这些组件中的每一个都派生自抽象的
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);
    }
}
您会选择哪种策略,或者您有更好的主意? 提前致谢!     

解决方法

        可能的选择: 如您所说,如果可搜索性/选择性实现是通过策略模式(依赖注入)提供的,那么我认为ISearchable和ISelectable的接口是一个更好的主意。 您可以从这些接口派生您的策略对象,并在基本组件类GetSearchable(),GetSelectable()中为它们实现吸气剂-其中Component中的默认实现返回null(或者如果您没有接口的实现,不喜欢null)。     ,        为什么不使用装饰器?
Component c = new Component ();
var selectableAndSearchableOne = new SelectableComponent (new SearchableComponent (c));
    ,        好的,另一个:这次您也知道了组件的扩展点。像游客一样的图案
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
        }
    }