问题描述
|
我目前遇到一个设计问题。
假设有一个组件层次结构。这些组件中的每一个都派生自抽象的
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
}
}