EngineerSpock
@EngineerSpock

Проектирование двух схожих классов, разделяющих множество свойств и методов (но не всех)?

Ситуация такая.

Есть два принтера от разных производителей. Мы хотим, чтобы верхний уровень ничего о них не знал и просто пользовался классом с единым набором методов и свойств.


Начинаю выделять интерфейс.

public interface IPrinterProvider {
        bool Connect(string comPort);
        bool IsConnected();
    }



Но выясняется, что одному принтеру нужно передавать пароль для исполнения множества операций, а другому нет.

Как быть?


И ещё.

Как я понимаю, у меня здесь должен получиться один или пару интерфейсов и пару наследников.

А как будет работать вызывающая сторона?

Мне нужно создать отдельный для неё класс, который никаких интерфейсов, в принципе, может и не реализовывать? Например:
public class CommonPrinterProvider {
        private IPrinterProvider printerProvider;
        public CommonPrinterProvider(IPrinterProvider printerProvider) {
            this.printerProvider= printerProvider;
        }
    }



Итого два вопроса.
  • Вопрос задан
  • 3529 просмотров
Пригласить эксперта
Ответы на вопрос 5
taliban
@taliban
php программист
Абстрактный класс не рассматривается как родитель? На сколько я понимаю много кода будет общего, интерфейс прекрасно заменяется абстрактным классом + сколько нужно наследников.
Ответ написан
Комментировать
@alexus_ru
Может быть как то так? интерфейс общий, просто у одного принтера придется переопределить методы для вызова нового с передачей пароля. Я идеале он сможет использовать методы базового абстрактного класса.
Код на pastebin
Ответ написан
Комментировать
@kxyu
Вопрос в том, откуда будет браться этот пароль? Его может передавать тот самый «верхний уровень», который будет передавать принтеру команды или какой-то другой объект, который будет конфигурировать объект принтера; как вариант — объект-factory. В этом объекте можно захардкодить конфигурирование для разных реализаций интерфейса; альтернативный вариант — принять в качестве обобщения, что пароль может быть, а может и не быть, и в этом случае мы передаем пустую строку, например. Конкретная реализация может использовать или не использовать этот пароль. Итого имеем:
  • конфигурационный файл, в котором как минимум два поля — класс принтера и пароль (необязательно);
  • объект-factory, который читает файл и инстанцирует объект указанного класса и задает ему пароль и остальные параметры;
  • вызывающая сторона создает объект и использует его через интерфейс.
Ответ написан
Комментировать
haiku
@haiku
В конкретный принтер должна инжектаться фабрика получения настроек, либо сразу настройки напрямую. Выделять какие-то пароли в интерфейс самого принтера нецелесообразно. Юзать пароль или не юзать это вопрос связи с сущностью "настройки принтера" или что-то такое, но не сам "принтер". Сам принтер должен уметь разве что печатать непосредственно, да и то, вероятно, делигировать на "печатающая часть принтера" или подобное.
Основой выделения общего предка является общая ответственность, общее поведение. В данном случае "есть пароль/не есть пароль" - это ни общая ответственность ни общее поведение, а всего-лишь одна из зависимостей, необходимых только одному из типов принтеров.
Ответ написан
Комментировать
@Oxoron
Шарпер
Так как пароль не нужен одному из принтеров, незачем вносить его в методы интерфейса (абстрактного класса). Проще передавать в конструкторе конкретного наследника.
При желании, можно сделать необязательным параметром.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы