基于界面的设计问题
本文关键字:问题 界面 于界面 | 更新日期: 2023-09-27 18:08:08
我的问题是关于类的设计。在这里很难解释所有的事情,所以我举一个和我的问题类似的例子。
需求:客户可以执行单个操作,也可以组合多个操作。
基于上述要求,类的结构如下:
interface ICustAction
{
void Execute();
}
class CustAction:ICustAction
{
// this class contains a single action to be performed
public void Execute()
{
//should execute customer action
}
}
class CustActionCollction:ICustAction
{
// list of actions to be performed
private List<CustAction> _custActions;
public void Execute()
{
//should execute all the customer action in the list
}
}
class ExecutionEngine
{
public void Execute(ICustAction action)
{
//executes customer action/ customer action collection based on reference
action.Execute();
}
}
新要求:客户应该能够在CustActionCollection中添加CustActionCollection。
的例子:客户动作收集:客户行动1:客户行为2:客户操作集合1:(此操作集合可能有多个客户操作)客户行动3:
基于这些需求,更新后的CustActionCollection类看起来像这样
class CustActionCollction:ICustAction
{
// list of actions to be performed
private List<ICustAction> _custActions;
public void Execute()
{
//should execute all the customer action in the list
}
}
现在这是我需要专家意见的新要求。
我需要检查一个特定的操作是否在客户操作集合中定义了不止一次??
客户动作收集:客户行动1:客户行为2:客户操作集合1:(此操作集合可能有多个客户操作)客户行动3:
所以,检查应该是递归的,包括所有子集合。
问题:
我应该在接口内部添加这个检查方法,还是应该专门用于客户操作集合类??
A)如果方法是在接口中定义的,那么两个类的方法和实现的签名是什么?
B)如果方法不在接口中,那么该方法的实现将是什么?
如果我没有解释清楚,我很抱歉。如果我理解你的问题,似乎检查重复只需要在CustActionCollection
的情况下发生。因此,我认为你最好的实现是:
- 依赖Equals实现来检查
CustAction
是否相等。(不需要,但在我看来是最有意义的)。 -
在
CustCollection.evaluate()
方法中,生成所有CustActions
的主列表并检查是否重复。它看起来像这样(在CustActionCollection
类中):public void Execute() { //should execute all the customer action in the list if (DuplicatesExist()) { // Handle error } } private bool DuplicatesExist() { List<CustAction> actions = ProcessCollection(this); for (int x = 0; x < actions.Count; x++) { for (int y = x + 1; y < actions.Count; y++) { if(actions[x].Equals(actions[y]) { return true; } } } return false; } // Recursively get all customer actions private List<CustAction> ProcessCollection(CustActionCollction actions) { List<CustAction> ret = new List<CustAction>(); foreach (ICustAction action in actions._custActions) { if (action is CustActionCollction) { ret.AddRange(ProcessCollection(action as CustActionCollction); } else { ret.Add(action as CustAction); } } return ret; }
我可以想到几种方法来做到这一点:
- 在收集中定义检查方法。在这个方法中,迭代器遍历集合中的各个元素,构建一个
CustAction
的列表。当一个元素是CustActionCollection
时,需要一个运行时类型检查来迭代所包含的动作。 - 在
ICustAction
中创建方法containsAction
。CustAction
通过比较this
来实现它
我会这样做:(我不知道您是只想检查重复还是不执行重复,所以这里都有)。
<<p> 两个接口/strong>interface ICustAction
{
void Execute();
}
interface ICustActionCollection : ICustAction
{
List<ICustAction> Actions { get; }
List<ICustAction> GetAllActions();
void ExecuteDistinct();
bool HasDuplicates();
}
ICustActionCollection将处理整个问题。
让我们看看实现:
class CustAction : ICustAction
{
public void Execute()
{
}
}
class CustActionCollection : ICustActionCollection
{
private List<ICustAction> _actions;
public List<ICustAction> Actions
{
get
{
if (_actions == null)
{
_actions = new List<ICustAction>();
}
return _actions;
}
}
public void Execute()
{
foreach (var action in _actions)
{
action.Execute();
}
}
public void ExecuteDistinct()
{
List<ICustAction> executionList = GetAllActions();
foreach (var action in distinctActions(executionList))
{
action.Execute();
}
}
public List<ICustAction> GetAllActions()
{
Stack<ICustAction> actions = new Stack<ICustAction>();
List<ICustAction> executionList = new List<ICustAction>();
actions.Push(this);
while (actions.Count > 0)
{
ICustAction action = actions.Pop();
if (action is ICustActionCollection)
{
foreach (var i in ((ICustActionCollection)action).Actions)
{
actions.Push(i);
}
}
else
{
executionList.Add(action);
}
}
return executionList;
}
public bool HasDuplicates()
{
List<ICustAction> actions = GetAllActions();
return distinctActions(actions).Count() < actions.Count;
}
private IEnumerable<ICustAction> distinctActions(IEnumerable<ICustAction> list)
{
return list.Distinct();
}
}
ICustAction的实现很简单。
在CustActionCollection类中,您实现了这两个接口。
方法:
distinctActions你的自定义实现什么是distinct?我在这里使用默认值,但是您可以在类CustAction中重写Equals和GetHashCode方法来定义什么是副本。
GetAllActions将'递归'返回整个ICustAction列表。
ExecuteDistinct和 hasduplicate 正在使用GetAllActions和distinctActions来实现他们的目标(我认为这些方法是明确的,让我知道如果不是)。
你可以测试它,如果你改变CustAction类为:
class CustAction : ICustAction
{
public int ID { get; private set; }
public CustAction(int id)
{
ID = id;
}
public void Execute()
{
Console.WriteLine("Execute: {0}", ID);
}
}
然后运行这个:
static void Main(string[] args)
{
CustAction a = new CustAction(1);
CustAction b = new CustAction(2);
CustAction c = new CustAction(3);
CustActionCollection coll = new CustActionCollection();
CustActionCollection coll2 = new CustActionCollection();
coll.Actions.Add(a);
coll.Actions.Add(b);
coll.Actions.Add(coll2);
coll2.Actions.Add(a);
coll2.Actions.Add(c);
Console.WriteLine("Without distinct");
coll.Execute();
Console.WriteLine("With distinct");
Console.WriteLine("Has duplicates: {0}", coll.HasDuplicates());
coll.ExecuteDistinct();
coll2.Actions.Remove(a);
Console.WriteLine("Duplicate removed, simple Execute");
Console.WriteLine("Has duplicates: {0}", coll.HasDuplicates());
coll.Execute();
}
输出将是这样的:
Without distinct
Execute: 1
Execute: 2
Execute: 1
Execute: 3
With distinct
Has duplicates: True
Execute: 3
Execute: 1
Execute: 2
Duplicate removed, simple Execute
Has duplicates: False
Execute: 1
Execute: 2
Execute: 3
EDIT:我将ICustActionCollection接口更改为
ICustactionCollection: ICustAction
如果一个类实现了ICustActionCollection你可以确定它也会实现ICustAction
暗线
这一切都取决于这个结构需要什么其他的改变(如果有的话)以及如何比较动作。假设您已经可以将任意ICustAction与其他ICustAction进行比较:我不建议把重复检查方法的接口,因为它会完全相同的所有实现的情况下,你这样做,以后如果你想做一些小变化的内部运作dupliaction检查你需要的代码(我们最有可能尽量避免这些siutations oop,不仅仅因为它是更舒服,但因为是什么更舒适也会有更少的错误)。
如果我是你,我会把一些助手属性到ICustAction,它提供了所有需要的信息(唯一标识符,如果你喜欢)的复制检查器方法比较一个与另一个。此时,您可以在custactioncollection中编写一次检查器。
问候,彼得