Специальные сервисы для разных типов моделей в ООП

#oop #design-patterns

#ооп #шаблоны проектирования

Вопрос:

Этот вопрос не зависит от языка для языков ООП.

У меня есть два класса: DeviceA и DeviceB , которые наследуются от класса модели Device . Мне нужно реализовать две службы DeviceAService и DeviceBService , которые наследуются от DeviceService . Мой язык не поддерживает обобщения, и мне нужно реализовать методы с Device параметром в DeviceService , которые будут переопределены в DeviceAService и DeviceBService и реализованы по-разному в зависимости от типа Device . Затем я хочу вызвать эти функции из общего DeviceService .

Какова наилучшая практика для разработки этого? Нельзя if ли здесь избежать использования и проверки типа класса? Еще одна идея для оптимальной реализации этого дизайна?

Комментарии:

1. Это звучит как процедурное программирование, а не ООП. Данные находятся в одном классе; логика — в другом. Вы должны передать структуру данных в процедуру. ООП объединит их и реализует логику в одном классе с необходимыми данными. Тогда логика становится полиморфной.

2. У вас могут быть классы DeviceA и DeviceB, наследуемые от устройства, а также от службы смешивания, или устройство наследуется от (или используется) службы, если нет множественного наследования (и, возможно, тогда смешивание называется интерфейсом)

3. Также возможно, чтобы объекты содержали специализированные объекты-службы.

Ответ №1:

Если я правильно понимаю вопрос, у вас есть абстрактный базовый класс, подобный этому:

 public abstract class DeviceService
{
    public abstract void DoSomething(Device device);
}
  

Вы хотите реализовать DeviceAService и DeviceBService так, чтобы их поведение отличалось в зависимости от типа Device .

Полиморфизм

Наиболее объектно-ориентированный дизайн заключается в использовании полиморфизма. Поскольку Device он уже полиморфен, поместите поведение, которое вы хотите изменить, в полиморфный метод и вызовите его из своего сервиса:

 public override void DoSomething(Device device)
{
    // Perhaps do something first...
    device.DoThePolymorphicThing();
    // Perhaps do something else after...
}
  

Реализуйте DoThePolymorphicThing по-разному в DeviceA и DeviceB .

Открытый мир

Если вы не можете изменить API Device базового класса, и вам также необходимо поддерживать другие реализации, кроме DeviceA and DeviceB , вам, вероятно, потребуется выполнить проверку во время выполнения DoSomething :

 public override void DoSomething(Device device)
{
    if (device is DeviceA)
        // Do something...
    else if (device is DeviceB)
        // Do something else...
    else
        // remember to handle the case where it's neither A nor B
}
  

Мы можем назвать этот тип сценария «открытым миром», потому Device что он открыт для расширения.

Закрытый мир

Если, с другой стороны, вы знаете, что у вас будет только DeviceA и DeviceB , шаблон проектирования посетителя — это именно то, что вам нужно:

 public interface IDeviceVisitor
{
    void VisitA(DeviceA device);
    void VisitB(DeviceB device);
}

public abstract class Device
{
    public abstract void Accept(IDeviceVisitor visitor);
    // Other members go here if you need them...
}

public class DeviceA : Device
{
    public override void Accept(IDeviceVisitor visitor)
    {
        visitor.VisitA(this);
    }

    // Other overrides, if needed, go here...
}

// Define DeviceB in the same way...
  

Теперь вы можете реализовать сервис следующим образом:

 public override void DoSomething(Device device)
{
    // Perhaps do something first...
    device.Accept(new MyDeviceVisitor());
    // Perhaps do something else after...
}
  

Вы можете думать об этом сценарии как о сценарии «закрытого мира», потому что вы не можете добавить третий тип устройства без изменения API посетителя (и, следовательно, нарушения существующих реализаций).

Комментарии:

1. Я нахожу ваш подход очень интересным. Однако я бы предпочел сохранить свои классы устройств в виде простых моделей и не внедрять в них какие-либо методы бизнес-логики. Я бы предпочел реализовать свои методы в сервисах. Тем не менее, ваш вклад очень полезен и является жизнеспособным подходом.