使用C#中的接口进行设计

时间:2018-09-21 14:28:16

标签: c# design-patterns interface

问题

我有一个设计问题,无法解决克利夫利。我敢肯定有一个不错的解决方案,但我不知道该如何实现。我仍然设法完成我的代码工作,但是结果很丑陋,我想学习更好的设计。

我竭尽所能提供最小的实现。因此,某些方面可能看起来很奇怪。我希望我能弄清楚自己。

上下文

所以首先,我有这些简单的类,它们都实现了相同的接口:

public interface Human
{
    string getName();
}

public class Adult : Human
{
    public Adult(string name, string job)
    {
        Name = name;
        Job = job;
    }

    public string Name { get; set; }
    public string Job { get; set; }
    public string getName()
    {
        return Name;
    }
}

public class Child : Human
{
    public Child(string name, string toy)
    {
        Name = name;
        Toy = toy;
    }

    public string Name { get; set; }
    public string Toy { get; set; }

    public string getName()
    {
        return Name;
    }
}

我在另一个更复杂的类中使用这些类,这些类基本上具有以下结构:

class MasterClass
{
    public string Name;
    public string Job;
    public string Toy;

    private ObservableCollection<Adult> ListOfAdults;
    private ObservableCollection<Child> ListOfChildren;
    private ObservableCollection<Human> CurrentList;  // Will point to one of the above list


    public void InitiateLists()
    {
        // Populate above lists with data
    }


    public Human CurrentHuman;

    public void ManageAdults()
    {
        CurrentList = new ObservableCollection<Human>(ListOfAdults);
    }

    public void ManageChildren()
    {
        CurrentList = new ObservableCollection<Human>(ListOfChildren);
    }

    public void setOtherHuman()
    {
        // Sets CurrentHuman as another adult/child according to currently managed list
    }

    public void SetManager(string newType)
    {
        switch (newType)
        {
            case "adult":
                ManageAdults();
                break;
            case "child":
                ManageChildren();
                break;
        }
    }

    void UpdateInfo()
    {
        // Set Name and Toy/Job according to currently managed human
    }

    void PrintInfo()
    {
        // Print Name and Toy/Job according to currently managed human
    }
}

这是我当前实现的框架,由于其他限制,我无法修改某些方面。在此类中,我希望方法PrintInfo()和UpdateInfo()的行为不同,具体取决于CurrentHuman是成人还是儿童。

到目前为止

在两种方法和某些强制转换中,我都设法使其采用夹心格式。像这样:

void UpdateInfo(string currentType)
        {
            Name = CurrentHuman.getName();
            switch (currentType)
            {
                case: "adult":
                    Job = ((Adult) CurrentHuman).Job;
                    break;
                case: "child":
                    Toy = ((Child) CurrentHuman).Toy;
                    break;
            }
        }

这确实不是理想的。在我的实际设计中,我有很多类型,其他方法的行为也取决于CurrentItem的类型。所以我现在淹没在开关柜中。这使我的代码混乱,重复并且很难维护。

可能的接口解决方案

由于我刚刚发现它们,所以我认为我可以使用接口。我已尽力而为,但找不到解决方案。

我想到了一个像这样的简单界面:

public interface IUpdater
    {
        void UpdateData(); // Takes the values from CurrentHuman and store them in the private members Name and Job/Toy depending on current type.
        void Print();
    }

我还以两种不同的方式实现我的界面:

class AdultUpdater : IUpdater
    {
        public void Print()
        {
            // Print Adult stuff only
        }

        public void UpdateData()
        {
            // Update Adult data only. 
        }
}

和类似的class ChildUpdater : IUpdater。它们都实现了针对儿童/成人的专用代码。

如果我将private IUpdater Updater声明为MasterClass的私有成员,则可以这样更改我的方法ManageAdult()ManageChildren()

 public void ManageAdults()
        {
            CurrentList = new ObservableCollection<Human>(ListOfAdults); // Same as before
            Updater = new AdultUpdater(); // Specify implementation to use
        }

(与ManageChildren()类似)。

然后我可以像这样出色地实现我的UpdateInfo()

 void UpdateInfo()
        {
            Updater.UpdateData();
        }

和我的PrintInfo()方法如下:

 void PrintInfo()
        {
            Updater.Print();
        }

界面真的很棒!哦,但是等等...

新问题

这似乎很有希望。我的问题是我不知道如何实现class AdultUpdater()class ChildUpdater()的代码。更准确地说,这两个类需要访问MasterClass的私有成员,即成员NameJobToyUpdateData()需要修改它们,而Print()需要显示它们。在这一点上,我感到非常愚蠢,非常接近一个非常明智的解决方案。有人知道如何完成此设计吗?

谢谢您的阅读...很抱歉,如果可以将此问题简化为更简洁的问题。我觉得需要一些有关当前实现的细节才能获得合适的答案。

2 个答案:

答案 0 :(得分:1)

正如我所见,您正在尝试“管理”您的人类。只是让他们自己做这项工作。 f.e.不要从经理/大师班打印并决定要打印什么,而要从人类那里获取打印的数据(即使只是部分,但不同的部分),也要将它们放到大师班中。

为您使用多态。他们(您的对象/人类)已经知道要打印或更新的内容,因此让他们来完成工作。尝试分散工作,而不是将所有工作都归为一类。

答案 1 :(得分:0)

这是我的建议,

您有一个与您的IHuman相对应的Human类,就像这样

public class Human : IHuman
{
    public Human(string name, string job)
    {
        Name = name;
        Job = job;
    }

    public string Name { get; set; }
    public string Job { get; set; }
    public string getName()
    {
        return Name;
    }
}

然后,您的成人和儿童类将继承Human类并传回构造函数值。

    public Adult(string name, string job) : base (name, job)
    {

    }

创建成人实例时,您将传入名称和工作,并且可以调用getName,因为它将继承自Human类。