SOLID 设计原则 In C# 代码实现
[S] Single Responsibility Principle (单一职责原则)
认为一个对象应该仅只有一个单一的职责
namespace SingleResponsibilityPrinciple { class DataAccess { void InsertData() { Console.WriteLine("数据插入成功"); } // 错误的设计,不符合 单一职责原则 //void WriteLog() //{ // Console.WriteLine("日志插入成功"); //} } // 应该把不同的职责交给不同的对象处理 class Logger { void WriteLog() { Console.WriteLine("日志插入成功"); } } }
[o] Open Close Principle (开闭原则)
认为软件应该是对扩展开放的,而对修改是关闭的
namespace OpenClosePrinciple { abstract class DataProvider { public abstract void OpenConnection(); public abstract void CloseConnection(); public abstract void ExecuteCommand(); } // MS SQL class SqlDataProvider:DataProvider { public override void OpenConnection() { Console.WriteLine("打开Sql数据连接"); } public override void CloseConnection() { Console.WriteLine("关闭Sql数据连接"); } public override void ExecuteCommand() { Console.WriteLine("执行Sql数据命令"); } } // ORACLE class OracleDataProvider:DataProvider { public override void OpenConnection() { Console.WriteLine("打开Oracle数据连接"); } public override void CloseConnection() { Console.WriteLine("关闭Oracle数据连接"); } public override void ExecuteCommand() { Console.WriteLine("执行Oracle数据命令"); } } class Start { void Invoke() { DataProvider dataProvider = new SqlDataProvider(); dataProvider.OpenConnection(); dataProvider.ExecuteCommand(); dataProvider.CloseConnection(); dataProvider = new OracleDataProvider(); dataProvider.OpenConnection(); dataProvider.ExecuteCommand(); dataProvider.CloseConnection(); } } }
[L] Liskov Substitution Principle(里氏替换原则)
认为程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换的
namespace LiskovSubstitutionPrinciple { class Rectangle { protected int width = 0; protected int height = 0; public virtual void SetWidth(int width) { this.width = width; } public virtual void SetHeight(int height) { this.height = height; } public virtual int GetArea() { return this.width * this.height; } } class Square : Rectangle { public override void SetHeight(int height) { this.height = height; this.width = height; } public override void SetWidth(int width) { this.height = width; this.width = width; } } class Start { public static Rectangle CreateInstance(int condition = 1) { if (condition == 1) { return new Rectangle(); } else { return new Square(); } } public static void Invoke() { Rectangle rectangleObject = CreateInstance(); rectangleObject.SetHeight(10); rectangleObject.SetWidth(20); rectangleObject.GetArea(); } } }
[I] Interface Segregation Principle(接口分离原则)
认为多个特定客户端接口要好于一个宽泛用途的接口,也有单一职责的意思
namespace InterfaceSegregationPrinciple { interface IDataProvider { void OpenConnection(); void CloseConnection(); } interface ISqlDataProvider : IDataProvider { void ExecuteSqlCommand(); } interface IOracleDataProvider : IDataProvider { void ExecuteOracleCommand(); } class SqlDataProvider : ISqlDataProvider { public void ExecuteSqlCommand() { Console.WriteLine("执行Sql数据命令"); } public void OpenConnection() { Console.WriteLine("打开Sql数据连接"); } public void CloseConnection() { Console.WriteLine("关闭Sql数据连接"); } } class OracleDataProvider : IOracleDataProvider { public void ExecuteOracleCommand() { Console.WriteLine("执行Oracle数据命令"); } public void OpenConnection() { Console.WriteLine("打开Oracle数据连接"); } public void CloseConnection() { Console.WriteLine("关闭Oracle数据连接"); } } class Start { public void Invoke() { ISqlDataProvider sqlDataProvider = new SqlDataProvider(); sqlDataProvider.OpenConnection(); sqlDataProvider.ExecuteSqlCommand(); sqlDataProvider.CloseConnection(); IOracleDataProvider oracleDataprovider = new OracleDataProvider(); oracleDataprovider.OpenConnection(); oracleDataprovider.ExecuteOracleCommand(); oracleDataprovider.CloseConnection(); } } }
[D] Dependency Inversion Principle(依赖反转原则)
认为一个方法应该遵从依赖于抽象而不是一个实例,控制反转,依赖注入是该原则的一种实现
namespace DependencyInversionPrinciple { interface IBankAccount { long BankNumber { get; set; } // 卡号 decimal Balance { get; set; } // 余额 } // 转账人 interface ITransferSource : IBankAccount { void CutPayment(decimal value); } // 收款人 interface ITransferDestination : IBankAccount { void AddMoney(decimal value); } class BankAccout : IBankAccount, ITransferSource, ITransferDestination { public long BankNumber { get; set; } public decimal Balance { get; set; } public void CutPayment(decimal value) { Balance -= value; } public void AddMoney(decimal value) { Balance += value; } } class TransferAmount { public decimal Amount { get; set; } public void Transfer(ITransferSource source, ITransferDestination dest) { source.CutPayment(Amount); dest.AddMoney(Amount); } } class Start { void Invoke() { ITransferSource source = new BankAccout { Balance = 10000, BankNumber = 111 }; ITransferDestination dest = new BankAccout { Balance = 1, BankNumber = 222 }; TransferAmount transfer = new TransferAmount(); transfer.Amount = 9999; // 转多少钱 transfer.Transfer(source, dest); // 开始转账 // 这是用依赖反转的思维做一个银行转账的功能,使银行账户可以依赖ITransferSource,ITransferDestination // 而不是以前直接 BankAccout account = new BankAccout();大大增加了账户这个核心对象的灵活性 // 这个例子基本上有SOLID原则的所有身影 } } // 附上一个普通版的 做下对比,用中文名做变量,通俗易懂吧 class 银行账户 { public int 卡号 { get; set; } public decimal 余额 { get; set; } public void 存入(decimal value) { 余额 += value; } public void 支出(decimal value) { 余额 -= value; } } class 银行转账操作 //ATM { public 银行账户 转账人 { get; set; } public 银行账户 收款人 { get; set; } public decimal 金额 { get; set; } public void 转账() { 转账人.支出(金额); 收款人.存入(金额); } } class Start1 { public void Main() { 银行账户 张三 = new 银行账户 { 卡号 = 111, 余额 = 10000 }; 银行账户 李四 = new 银行账户 { 卡号 = 222, 余额 = 5 }; 银行转账操作 转账 = new 银行转账操作(); 转账.金额 = 1000; 转账.转账人 = 张三; 转账.收款人 = 李四; 转账.转账(); } } }
SOLID设计原则是个老生常谈的话题了,在博客园居然没找到良好的代码实现,所以就自己参考网上的资料写了这么一篇博客,技术含量不高,给新手看的,包括我,个人认为掌握了这五点设计原则,并熟练运用于自己的系统中还是得花点时间的。反正我的观点就是:业务领域驱动设计原则。如果你不熟悉业务领域,你根本发挥不了这其中的优点,你会认为这样做反而麻烦了,但是又对于什么设计原则什么设计模式出于崇高的敬意,把网上书上的那些例子照着敲一遍二遍三遍。。。你会的也只不过是会写各种原则,模式的代码模板而已。so,学习设计模式的好方法是先弄懂一套业务领域的逻辑,然后在用你学到的设计模式的思想去挑刺儿。领域驱动模式设计给了我很大的启发,先敬畏业务领域,再敬畏软件设计,最后敬畏代码。当然平时也要用敬畏之心去看待事物。