依赖倒转(DIP):高层模块不应该依赖低层模块,他们都依赖抽象,抽象不应该依赖于细节,细节应该依赖于抽象。即 应当针对接口编程,不要针对实现编程,使用抽象类或接口进行变量和方法进行声明,而不应当由实现类去做这些事情。
先介绍几个概念
单一职责原则:一个类的功能尽可能少,这样才可以降低耦合有利于复用
开闭原则:软件应当在不修改源码的情况下进行扩展
Software Entity Should be open for Extension but close for modification
里氏代换:任何引用基类的地方都可以透明的使用其子类对象。即 软件中将一个子类替换为它的基类,程序不会产生任何影响
接口隔离原则(ISP): 客户端不应该依赖那些不要的接口。即 接口职责单一化,不要强迫客户依赖于那些他们不用的方法
合成复用(CRP): 优先使用组合和聚合的方式复用,防止滥用继承,分清IsA HasA,
迪米特法则(LoD):要求一个实体竟可能少的与其他实体发生相互作用
接下来看代码:
public class CustomDAO
{
public void AddTXTUser(TXTDataConvertor convertor)
{
Console.WriteLine("Finished Add User:" + convertor.ReadFile());
}
public void AddExcelUser(ExcelDataConvertor convertor)
{
Console.WriteLine("Finished Add User:" + convertor.ReadFile());
}
}
public class TXTDataConvertor
{
public string ReadFile()
{
var userName = "小熊";
Console.WriteLine("TXTDataConvertor=> Reading User:" + userName);
return userName;
}
}
public class ExcelDataConvertor
{
public string ReadFile()
{
var userName = "大熊";
Console.WriteLine("ExcelDataConvertor=> Reading User:" + userName);
return userName;
}
}
class Program
{
static void Main(string[] args)
{
var CRM =new CustomDAO();
CRM.AddTXTUser(new TXTDataConvertor ());
CRM.AddExcelUser(new ExcelDataConvertor());
}
}
该CRM系统中需要从TXT和Excel中导入数据,如果针对每种导入方法都需要在CustomDAO中写上相应的方法,如果客户需求变更,比如要将TXT改为Word,那么就必须修改CustomDAO的源代码,违反了开闭原则
接下来进行改进
public interface IDataConvertor
{
string ReadFile();
}
public class CustomDAO
{
public void AddUser(IDataConvertor convertor)
{
Console.WriteLine("Finished Add User:" + convertor.ReadFile());
}
}
public class TXTDataConvertor: IDataConvertor
{
public string ReadFile()
{
var userName = "小熊";
Console.WriteLine("TXTDataConvertor=> Reading User:" + userName);
return userName;
}
}
public class ExcelDataConvertor : IDataConvertor
{
public string ReadFile()
{
var userName = "大熊";
Console.WriteLine("ExcelDataConvertor=> Reading User:" + userName);
return userName;
}
}
public class WordDataConvertor : IDataConvertor
{
public string ReadFile()
{
var userName = "老熊";
Console.WriteLine("WordDataConvertor=> Reading User:" + userName);
return userName;
}
}
class Program
{
static void Main(string[] args)
{
var CRM =new CustomDAO();
//如果将下面的代码通过读取配置文件结合反射实例化,将不用修改任何源代码,即可达到需求,如果需要增加导入方法,也不会修改到CustomDAO源代码,符合 开闭原则
IDataConvertor conver = new WordDataConvertor();//这里可以改进为读取配置文件
CRM.AddUser(conver);
// CRM.AddUser(new WordDataConvertor());
}