什么是设计模式?
根据实际开发经验设计出来的程序搭建框架,可以较好的解决一些开发中遇到的问题。
常见设计模式?
常见设计模式有23种。如简单工厂设计模式、抽象工厂设计模式、单例设计模式等,目前学习前两种模式。
简单工厂设计模式
问题引入:
接到新的开发需求,设计多种报表,如Excel报表、Word报表或其他报表,我们可以根据每家公司的需求,去让程序实现该公司所使用的的报表。问题是,如何能最简单快速的使程序选择相应的报表形式呢?
简单工厂概念:
通过“简单工厂”这样的形式,来根据实际需求创建我们所选择的接口的实现类,从而实现一个选择功能。
代码示例:
先创建接口
namespace SampleFactoryDemo { public interface IReport { void Report(); } }
创建接口实现类
namespace SampleFactoryDemo { public class ExcelReoprt:IReport { public void Report() { Console.WriteLine("正在使用Excel报表……"); } } }
namespace SampleFactoryDemo { class WordReport : IReport { public void Report() { Console.WriteLine("正在调用Word报表……"); } } }
创建App.Config文件,通过App.Config文件的相关节点来告诉程序我们需要哪种报表
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="ReportType" value="WordReport"/> <!--<add key="ReportType" value="ExcelReport"/>--> </appSettings> </configuration>
创建报表工厂,注意System.Configuration引用的添加
using System.Configuration; namespace SampleFactoryDemo { class ReportFactory { static string reportType = ConfigurationManager.AppSettings["ReportType"].ToString(); public static IReport ChooseReportType() { IReport objReport=null; switch (reportType) { case "ExcelReport": objReport = new ExcelReoprt();break; case "WordReport": objReport = new WordReport();break; } return objReport; } } }
Program
namespace SampleFactoryDemo { class Program { static void Main(string[] args) { IReport objReport = ReportFactory.ChooseReportType(); if (objReport != null) objReport.Report(); Console.ReadLine(); } } }
当我们去修改AppConfig文件里appSettings的值,就可以实现选择相应报表。需要注意的是:appSettings的key值出现重复时,程序会得到最后一个该key的value值
总结:
以上,我们初步实现了开发需求。当需要继续扩展的时候,只需添加相应报表实现类(或dll),在ReportFactory以App.Config里面添加相应报表的判断以及Key-Value。
问题引入:
以上需求实现,我们发现一个问题:每次当我们添加新报表类型时,都需要去修改-添加ReportFactory,这明显不符合“开-闭原则”---“开放扩展,封闭修改”。
问题解决:
使用反射机制来优化以上程序。反射介绍:http://www.cnblogs.com/EasonDongH/p/8108279.html
修改ReportFactory:
public static IReport ChooseReportType() { return (IReport)Assembly.Load("SampleFactoryDemo").CreateInstance("SampleFactoryDemo."+reportType); }
注意:引入System.Reflection;Load()里面是命名空间名称,CreateInstance()里面是完全限定名:命名空间.类名。
如此,每次添加新报表类型时,仅需添加相应报表实现、AppConfig相应keyValue,不需要对程序再做修改。