Запрос совета относительно дизайна класса, наследования / агрегации - PullRequest
4 голосов
/ 03 мая 2010

Я начал писать свой собственный класс сервера WebDAV в .NET, и первый класс, с которого я начинаю, это класс WebDAVListener, смоделированный по принципу работы HttpListener класса.

Поскольку я не хочу переопределять основную обработку протокола http, я буду использовать HttpListener во всей его ценности, и поэтому у меня возникнет вопрос.

Каким будет предложенный способ справиться с этим:

  • Реализуйте все методы и свойства, найденные внутри HttpListener, просто изменив типы классов там, где это имеет значение (т. Е. Методы GetContext + EndGetContext будут возвращать другой класс для контекстов WebDAV), а также сохраняя и используя объект HttpListener для внутреннего использования
  • Создайте WebDAVListener, передав ему класс HttpListener для использования?
  • Создать оболочку для HttpListener с интерфейсом и создать WebDAVListener, передав ему объект, реализующий этот интерфейс?

Если при прохождении маршрута передачи HttpListener (замаскированного или иным образом) в WebDAVListener, вы бы выставили базовый объект слушателя через свойство или ожидали, что программа, использовавшая класс, сохранит ссылку на базовый HttpListener

Также, в этом случае, вы бы раскрыли некоторые методы от HttpListener до WebDAVListener, такие как Start и Stop, или вы снова ожидаете, что программа, использовавшая его, будет поддерживать ссылку HttpListener для все эти вещи?

Моя первоначальная реакция говорит мне, что я хочу комбинацию. Прежде всего, я бы хотел, чтобы мой WebDAVListener класс выглядел как полная реализация, скрывая тот факт, что под ним есть HttpListener объект.

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

Один из способов, которым я мог бы решить это, был бы следующим:

public WebDAVListener()
    : WebDAVListener(new HttpListenerWrapper())
{
}

public WebDAVListener(IHttpListenerWrapper listener)
{
}

И тогда я реализовал бы все методы HttpListener (по крайней мере, все те, которые имеют смысл) в своем собственном классе, в основном просто связывая вызов с базовым объектом HttpListener.

Что вы думаете?

Последний вопрос: если я пойду по пути интерфейса, если предположить, что интерфейс отображает 1-к-1 на класс HttpListener и написан просто для того, чтобы добавить поддержку имитации, такой интерфейс называется оболочкой или адаптером?

1 Ответ

1 голос
/ 05 мая 2010

Сначала я отвечу на ваш последний вопрос: класс - это адаптер, если он реализует некоторый интерфейс ITarget, используя содержащийся объект, соответствующий какому-то ISource, - адаптер от ISource к ITarget. В этом случае нет исходного интерфейса, вы пытаетесь добавить его, поэтому я бы назвал его оболочкой.

Я был бы склонен к

  • Создайте класс WebDavListener, который имеет все методы, необходимые для его собственного поведения, использует внутренний HttpListener и ничего не раскрывает об этом HttpListener.

  • Если и когда вам это нужно , сделайте IHttpListenerWrapper и HttpListenerWrapper, как вы предлагаете, и измените WebDavListener так, чтобы он использовал IHttpListenerWrapper в своем конструкторе. Предполагая, что все методы одинаковы, это должен быть простой поиск и замена. Вы могли бы даже оставить оригинальный конструктор там, чтобы он создал оболочку и вызвал новый конструктор.

  • Если и когда вам это нужно , создайте IWebDavListener для его реализации, если вы считаете, что вам может понадобиться фиктивный слушатель WebDAV для модульного тестирования других вещей.

Именно из-за такого рода проблем с проектированием мне нравятся такие инструменты рефакторинга, как ReSharper: извлечение интерфейса, создание производной реализации и т. Д., Которые значительно упрощают внесение подобных изменений, поэтому вы можете меньше беспокоиться о том, делать их сейчас или позже: -) (Если, конечно, вам позже разрешено свободно менять источник, это зависит от того, как вы доставляете вещи.)

...