Программный шаблон для возврата конкретного результата из абстракций

#design-patterns #architecture #decoupling

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

Вопрос:

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

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

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

Это грубый пример общей структуры используемых абстракций, но все они открыты для пересмотра, если этого требует подходящее решение:

 interface IServiceResult {
    // No idea what methods this should have yet
}

interface IServiceHandler {
    IServiceResult CouldNotFindFile();
    IServiceResult CouldNotReadFile();
    IServiceResult ServiceSuccessful();
}

interface IService {
    IServiceResult PerformService(IServiceHandler outcomes);
}

// Console Client Code:
IService service = new Service();
IServiceHandler handler = new ConsoleServiceHandler();
IServiceResult result = service.PerformService(handler);
/* Some process to convert IServiceResult to text to display in the console */

// API Endpoint Client Code:
IService service = new Service();
IServiceHandler handler = new ApiServiceHandler();
IServiceResult result = service.PerformService(handler);
/* Some process to convert IServiceResult to Http Status Code to return to client */
  

Моя интуиция заключается в том, чтобы иметь какую-то двойную отправку с IServiceResult помощью, но я не могу разобраться / как получить желаемый результат с этого момента. Любая информация была бы очень признательна.

Ответ №1:

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

Было бы лучше использовать дизайн, который в первую очередь не требует этого ограничения.

Вы можете упростить свой интерфейс и избежать этой проблемы, полностью избавившись от IServiceResult

 interface IServiceResponder {
    void CouldNotFindFile();
    void CouldNotReadFile();
    void ServiceSuccessful();
}

interface IService {
    void PerformService(IServiceResponder responseTarget);
}

// Console Client Code:
IService service = new Service();
// this will print the response to the console when it is set
IServiceResponder responder = new ConsoleServiceResponder();
service.PerformService(responder);