如何自动注册新的子类



我正在研究我们Web应用程序的报告模块。有六个报告可供客户端使用,每个报告都有一个代码。问题是,现在该模块没有关闭以进行修改,以可能添加新报告,从而违反了OCP。

为了阐明,我有以下一组类:

所有其他报表继承的通用报表类:

public abstract class Report 
{
    private final String code;
    Report(String code)
    {
        this.code = code;
    }
    public String getCode() { return code; }
    public abstract byte[] generate();
}

一个 Servlet,用于管理用于生成报告的 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的任何新子类?

我认为

OCP更适合Report本身,并且ReportRegistry位于类层次结构之外将是一个有效的设计。

也就是说,如果要避免每次创建Report子类时都修改ReportRegistry,则可以使用一些反射技巧来查找所有此类子类,或者创建一个注释,ReportRegistry可以搜索该注释以将所有类注册到实例。

你应该

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

然后,您可以在ReportRegistry静态块中注册它们。

最新更新