我正在研究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
的任何新子类自动注册,而无需任何明确提及?
答案 0 :(得分:1)
我认为OCP更适合Report
本身,而将ReportRegistry
放在类层次结构之外将是一个有效的设计。
也就是说,如果您希望避免在每次创建ReportRegistry
子类时都修改Report
,则可以使用一些反射技巧来找出所有此类子类,或者创建一个{{1 }}可以搜索以向实例注册所有类。
答案 1 :(得分:0)
您应该查看https://github.com/ronmamo/reflections。我从未尝试过该库,但看起来它可以满足您的要求(检索已知类的所有子类)。
然后您可以将其注册到ReportRegistry
静态块中。