基于界面的设计问题

本文关键字:问题 界面 于界面 | 更新日期: 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的情况下发生。因此,我认为你最好的实现是:

  1. 依赖Equals实现来检查CustAction是否相等。(不需要,但在我看来是最有意义的)。
  2. 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;
     }
    

我可以想到几种方法来做到这一点:

  1. 在收集中定义检查方法。在这个方法中,迭代器遍历集合中的各个元素,构建一个CustAction的列表。当一个元素是CustActionCollection
  2. 时,需要一个运行时类型检查来迭代所包含的动作。
  3. ICustAction中创建方法containsActionCustAction通过比较this
  4. 来实现它

我会这样做:(我不知道您是只想检查重复还是不执行重复,所以这里都有)。

<<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中重写EqualsGetHashCode方法来定义什么是副本。

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中编写一次检查器。

问候,彼得