如何自动注册新的子类?

时间:2019-04-24 13:35:51

标签: java oop design-patterns

我正在研究Web应用程序的报告模块。客户可以使用六个报告,每个报告都有一个 code 。问题在于,就潜在的新报告添加而言,该模块现在尚未关闭以进行修改,从而违反了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请求以生成报告的servlet:

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 个答案:

答案 0 :(得分:1)

我认为OCP更适合Report本身,而将ReportRegistry放在类层次结构之外将是一个有效的设计。

也就是说,如果您希望避免在每次创建ReportRegistry子类时都修改Report,则可以使用一些反射技巧来找出所有此类子类,或者创建一个{{1 }}可以搜索以向实例注册所有类。

答案 1 :(得分:0)

您应该查看https://github.com/ronmamo/reflections。我从未尝试过该库,但看起来它可以满足您的要求(检索已知类的所有子类)。

然后您可以将其注册到ReportRegistry静态块中。