我目前遇到了一个设计问题。
假设有一个组件层次结构。这些组件中的每一个都源自抽象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);
}
}
您会选择哪种策略或者您有更好的想法?
提前致谢!
答案 0 :(得分:1)
可能的选择:
如果通过策略模式(依赖注入)提供可搜索性/可选择性实现,正如您所说,那么我认为ISearchable和ISelectable的接口是更好的主意。
您可以从这些接口派生您的策略对象,并在您的base-Component类中实现它们的getter - GetSearchable(),GetSelectable() - 其中Component中的默认实现返回null(或者是no-op实现的界面,如果你不喜欢null)。
答案 1 :(得分:0)
你为什么不使用装饰师?
Component c = new Component ();
var selectableAndSearchableOne = new SelectableComponent (new SearchableComponent (c));
答案 2 :(得分: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
}
}