在Java中开放封闭原则
在本教程中,我们将在java.open内学习开放的封闭设计原理是封闭原则是一个坚实的原则之一。
开放的封闭设计原则决定了"软件实体(类,模块,函数等)应打开扩展,但关闭修改"。
该定义由Bertrand Meyer提供。
一旦我们写了这个程序并测试了它,它就不应该再次修改,但它应该打开扩展。
如果我们修改已经测试了,可能会导致大量的另外努力测试它,也可能有机会用于引入新错误。
策略设计模式是开放封闭设计原理的另一个例子。
服务类可以使用各种策略根据要求执行某些任务,因此我们将保留服务类关闭但同时,通过引入将实现战略接口的新策略开放。
在运行时,根据需要,我们可以使用任何新策略调用服务类。
让我们在一个简单的例子的帮助下了解。
我们需要根据输入类型创建两种类型(CSV和XML)的报告。
请注意,应提供将来添加新的报告类型。
创建名为"reporttype.java"的枚举,如下所示。
package org.igi.theitroad; public enum ReportingType { CSV,XML; }
创建服务类名为ReportingService,如下所示:
package org.igi.theitroad; public class ReportingService { public void generateReportBasedOnType(ReportingType reportingType) { System.out.println("==================================="); System.out.println("Generating report based on Type"); System.out.println("==================================="); if("CSV".equalsIgnoreCase(reportingType.toString())) { generateCSVReport(); } else if("XML".equalsIgnoreCase(reportingType.toString())) { generateXMLReport(); } } private void generateCSVReport() { System.out.println("Generate CSV Report"); } private void generateXMLReport() { System.out.println("Generate XML Report"); } }
创建一个名为"generatereportmain.java"的主类,该类将称为ReportingService来生成报表。
package org.igi.theitroad; public class GenerateReportMain { public static void main(String[] args) { ReportingService rs=new ReportingService(); //Generate CSV file rs.generateReportBasedOnType(ReportingType.CSV); System.out.println(); //Generate XML file rs.generateReportBasedOnType(ReportingType.XML); } }
输出:
=================================== Generating report based on Type =================================== Generate CSV Report =================================== Generating report based on Type =================================== Generate XML Report
正如我们所看到的,这是一个简单的代码,正好工作。
我们已经测试了代码,并发现我们能够根据类型生成报表。
现在,我们需要创建一个更长的报告类型:Excel.if我们注意,如果我们需要更改如下:1)我们需要在Enum ReportingType中进行更改。
package org.igi.theitroad; public enum ReportingType { CSV,XML,EXCEL; }
2)我们需要在已测试的ReportingService类中进行更改。
package org.igi.theitroad; public class ReportingService { public void generateReportBasedOnType(ReportingType reportingType) { System.out.println("==================================="); System.out.println("Generating report based on Type"); System.out.println("==================================="); if("CSV".equalsIgnoreCase(reportingType.toString())) { generateCSVReport(); } else if("XML".equalsIgnoreCase(reportingType.toString())) { generateXMLReport(); } else if("Excel".equalsIgnoreCase(reportingType.toString())) { generateExcelReport(); } } private void generateCSVReport() { System.out.println("Generate CSV Report"); } private void generateXMLReport() { System.out.println("Generate XML Report"); } private void generateExcelReport() { System.out.println("Generate Excel Report"); } }
现在,我们可以生成如下的Excel报告。
package org.igi.theitroad; public class GenerateReportMain { public static void main(String[] args) { ReportingService rs=new ReportingService(); //Generate CSV file rs.generateReportBasedOnType(ReportingType.CSV); System.out.println(); //Generate XML file rs.generateReportBasedOnType(ReportingType.XML); System.out.println(); //Generate Excel file rs.generateReportBasedOnType(ReportingType.EXCEL); } }
输出:
=================================== Generating report based on Type =================================== Generate CSV Report =================================== Generating report based on Type =================================== Generate XML Report =================================== Generating report based on Type =================================== Generate Excel Report
正如我们所看到的,我们必须在许多我们已经测试的地方修改,我们需要再次重新测试所有函数。
开放的封闭设计原则
让我们看看开放的封闭设计原则如何能够解决问题。
创建ReportingService.java如下。
package org.igi.theitroad; public class ReportingService { public void generateReportBasedOnStrategy(ReportingStrategy reportingStrategy) { System.out.println("==================================="); System.out.println("Generating report based on Strategy"); System.out.println("==================================="); reportingStrategy.generateReport(); System.out.println(); } }
创建一个名为ReportingStrategy的接口,如下所示。
package org.igi.theitroad; public interface ReportingStrategy { void generateReport(); }
创建一个名为"csvreportingstreate.java"的类,用于生成CSV报告
package org.igi.theitroad; public class CSVReportingStrategy implements ReportingStrategy { @Override public void generateReport() { System.out.println("Generate CSV Report"); } }
创建一个名为"xmlreportingstreate.java"的类,用于生成XML报告
package org.igi.theitroad; public class XMLReportingStrategy implements ReportingStrategy { @Override public void generateReport() { System.out.println("Generate XML Report"); } }
让我们现在创建一个主类WenerateReportMain.java。
package org.igi.theitroad; public class GenerateReportMain { public static void main(String[] args) { ReportingService rs=new ReportingService(); //Generate CSV report ReportingStrategy csvReportingStrategy=new CSVReportingStrategy(); rs.generateReportBasedOnStrategy(csvReportingStrategy); //Generate XML report ReportingStrategy xmlReportingStrategy=new XMLReportingStrategy(); rs.generateReportBasedOnStrategy(xmlReportingStrategy); } }
输出:
=================================== Generating report based on Type =================================== Generate CSV Report =================================== Generating report based on Type =================================== Generate XML Report
假设我们想生成Excel报告。
我们需要创建以下更改:创建另一个名为"ExcelReportingstrate.java"的类。
package org.igi.theitroad; public class ExcelReportingStrategy implements ReportingStrategy { @Override public void generateReport() { System.out.println("Generate Excel Report"); } }
更改WenerateReportMain.java以添加调用代码。
package org.igi.theitroad; public class GenerateReportMain { public static void main(String[] args) { ReportingService rs=new ReportingService(); //Generate CSV report ReportingStrategy csvReportingStrategy=new CSVReportingStrategy(); rs.generateReportBasedOnStrategy(csvReportingStrategy); //Generate XML report ReportingStrategy xmlReportingStrategy=new XMLReportingStrategy(); rs.generateReportBasedOnStrategy(xmlReportingStrategy); //Generate Excel report ReportingStrategy ExcelReportingStrategy=new ExcelReportingStrategy(); rs.generateReportBasedOnStrategy(ExcelReportingStrategy); } }
输出:
=================================== Generating report based on Strategy =================================== Generate CSV Report =================================== Generating report based on Strategy =================================== Generate XML Report =================================== Generating report based on Strategy =================================== Generate Excel Report
正如我们所看到的,我们没有制作已经测试的任何更改报告服务。
我们只是添加了新的"ExcelReportingStrategy",它使我们能够生成Excel报告。