Дизайн с интерфейсами в C # - PullRequest
       0

Дизайн с интерфейсами в C #

0 голосов
/ 21 сентября 2018

Проблема

У меня проблема с дизайном, которую я не могу решить с умом.Я уверен, что есть подходящее решение, но я не могу понять, как этого добиться.Мне все еще удавалось работать над своим кодом, но результат ужасен, и я хочу изучать лучшие проекты.

Я приложил все усилия, чтобы обеспечить минимальную реализацию с минимальным минимумом.Поэтому некоторые аспекты могут выглядеть странно.Я надеюсь, что у меня все получится.

Контекст

Итак, во-первых, у меня есть эти простые классы, которые реализуют один и тот же интерфейс:

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 взрослым или потомком.

До сих пор

Мне удалось заставить его работать с swich-case в обоих методах и некоторых приведениях.Вот так:

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 личным членом моего мастер-класса, это позволит мне изменить мои методы 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, а именно членам Name, Job и Toy.UpdateData() необходимо изменить их, а Print() - отобразить их.Я чувствую себя настолько тупо застрявшим в этой точке, так близко к очень изящному решению.У кого-нибудь есть идеи, как доработать этот дизайн?

Спасибо, что прочитали ... Извините, если эту проблему можно было бы сократить до более краткого вопроса.У меня было чувство, что некоторые детали о моей текущей реализации были необходимы, чтобы получить подходящий ответ.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Вот то, что я советую,

У вас есть класс Human, соответствующий вашему IHuman, что-то вроде этого

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)
    {

    }

Когда вы создаете экземпляр Adult, вы передаете имя и задание и можете вызвать getName, поскольку он будет унаследован от класса Human.

0 голосов
/ 21 сентября 2018

Как я понимаю, вы пытаетесь "управлять" своими людьми.Просто позвольте им самим делать свою работу.Например, не печатайте из менеджера / мастер-класса и не решайте, что печатать, а получайте распечатанные данные (даже если только части, но отличающиеся друг от друга) от людей и просто складывайте все это вместе в мастер-классе.

Используйте Полиморфизм для вас.Они (ваши объекты / люди) уже знают, что распечатывать или обновлять, поэтому дайте им сделать работу.Попробуйте распределить работу, а не объединять ее в один класс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...