Как автоматически зарегистрировать новые подклассы? - PullRequest
2 голосов
/ 24 апреля 2019

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

Чтобы выяснить, у меня есть следующий набор классов:

Общий класс отчета, который наследуют все остальные отчеты:

public abstract class Report 
{
    private final String code;

    Report(String code)
    {
        this.code = code;
    }

    public String getCode() { return code; }

    public abstract byte[] generate();
}

Сервлет, который управляет запросами POST для генерации отчета:

public class ReportServlet extends HttpServlet
{

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        Report requested = ReportRegistry.lookup(req.getParameter("report_code"));
        byte[] bytes = requested.generate();
        // attach bytes to response
    }

}

Реестр отчетов, в котором хранятся все существующие отчеты для последующего доступа:

public class ReportRegistry
{
    private static final Map<String, Report> registry = new HashMap<>();

    static
    {
        // Violates OCP!
        registerReport( GlobalReport.getInstance() );
        registerReport( AvailablePackagesReport.getInstance() );
        registerReport( BadgeReport.getInstance() );
        registerReport( PlacementReport.getInstance() );
        registerReport( TerminalReport.getInstance() );
        registerReport( VerActReport.getInstance() );
    }

    private ReportRegistry() { }

    static void registerReport(final Report report)
    {
        registry.put(report.getCode(), report);
    }

    public static Report lookup(final String reportCode)
    {
        return registry.get(reportCode);
    }
}

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

Мой вопрос: как я могу сделать так, чтобы любой новый подкласс Report регистрировался автоматически, без какого-либо явного упоминания?

Ответы [ 2 ]

1 голос
/ 24 апреля 2019

Я бы подумал, что OCP будет более применим к Report, и что наличие ReportRegistry вне иерархии классов будет правильным решением.

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

0 голосов
/ 24 апреля 2019

Вы должны взглянуть на https://github.com/ronmamo/reflections. Я никогда не пробовал эту библиотеку, но похоже, что она делает то, что вам нужно (получение всех подклассов известного класса).

Затем вы можете зарегистрировать их в вашем ReportRegistry статическом блоке.

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