文章目录
- 项目地址
- 一、开放封闭原则
- 1.1 不好的版本
- 1.2 将BankProcess的实现改为接口
- 1.3 修改BankStuff类和IBankClient类
- 二、依赖倒置原则
- 2.1 高层不应该依赖于低层模块
- 2.1.1 不好的例子
- 2.1.2 修改:将各个国家的歌曲抽象
- 2.2 抽象不应该依于细节
- 2.2.1 不同的人开不同的车(接口注入)
- 2.2.2 构造函数注入
- 三、接口分离原则
- 四、The least knowledge principle
- 五、Composite Reuse Principel 合成复用原则
- 5.1 什么时候使用继承,什么时候使用复合原则
- 5.2 类于类之间的关系
- 六、简单工厂模式
- 6.1 不好的例子
- 6.2 使用简单工厂模式
- 七、工厂反射方法设计模式
项目地址
- 教程作者:老赵Net
- 教程地址:
https://www.bilibili.com/video/BV1Xv4y1T7by?spm_id_from=333.788.videopod.episodes&vd_source=791e6deaa9c8a56b1f845a0bc1431b71&p=5
- 代码仓库地址:
- 所用到的框架和插件:
C#
一、开放封闭原则
- 业务描述,不用需求得用户去银行办理不用的业务
- 分析业务:①该业务需要多少个对象?②每个对象的属性和行为是什么
- 确定对象:①用户对象,属性(存钱用户,取钱用户);②银行柜员,帮助用户处理不同的需求;③银行业务系统:处理存钱,取钱,转账的操作
1.1 不好的版本
public class Program
{public static void Main(){BankUsers bankUsers = new BankUsers();bankUsers.BankTpe = "存钱";BankStuff bankStuff = new BankStuff();bankStuff.HandleBandProcess(bankUsers); }
}public class BankUsers
{public string BankTpe { get; set; }
}public class BankStuff
{//实例化一个BankProcess对象用来处理银行业务private BankProcess bankProcess = new BankProcess();public void HandleBandProcess(BankUsers bankUsers){switch (bankUsers.BankTpe){case "存钱":bankProcess.SaveMoney();break;case "取钱":bankProcess.GetMoney();break;case "转账":bankProcess.Transfer();break;default:break;}}
}public class BankProcess
{public void SaveMoney(){Console.WriteLine("处理用户存钱");}public void GetMoney(){Console.WriteLine("处理用户取钱");}public void Transfer(){Console.WriteLine("处理用户转账");}
}
- 问题:
- BankProcess不符合单一职责原则,修改三个方法的时候,都会影响这个类
- 在BankStuff里全是case,如果代码里全是case,肯定不符合设计模式
1.2 将BankProcess的实现改为接口
- 如何判断一个类设计的好坏就是:当你要修改类里面重要的方法的时候,不会影响到方法的执行!例如:我们对BankProcess里的取钱方法进行修改时候,整个BankProcess类是没办法使用的,只能当我们把全部功能改好了之后,这个类才能使用;
- 就类似于修路,路的主要功能有人行道和车行道路,我们在修人行道的时候,不能影响到车行道的车辆通行,才是一个好类的设计思想。
public class Program
{public static void Main(){BankUsers bankUsers = new BankUsers();bankUsers.BankTpe = "存钱";BankStuff bankStuff = new BankStuff();bankStuff.HandleBandProcess(bankUsers);}
}public class BankUsers
{public string BankTpe { get; set; }
}public class BankStuff
{//传入接口private IBankProcess _bankProcess;public void HandleBandProcess(BankUsers bankUsers){switch (bankUsers.BankTpe){case "存钱":_bankProcess = new SaveMoney();_bankProcess.ProcessMoney();break;case "取钱":_bankProcess = new GetMoney();_bankProcess.ProcessMoney();break;case "转账":_bankProcess = new Transfer();_bankProcess.ProcessMoney();break;default:break;}}
}public interface IBankProcess
{void ProcessMoney();
}public class SaveMoney : IBankProcess
{public void ProcessMoney(){Console.WriteLine("处理用户存钱");}
}public class GetMoney : IBankProcess
{public void ProcessMoney(){Console.WriteLine("处理用户取钱");}
}public class Transfer : IBankProcess
{public void ProcessMoney(){Console.WriteLine("处理用户转账");}
}
改进的好处:BankProcess提取成为接口,这样修改存钱,取钱的方式时候,不会影响到存款取款的功能
1.3 修改BankStuff类和IBankClient类
- 用过抽象或者接口,对变化进行封装;
- 这里经常发生变化的就是传入的用户类型;所以,创建了一个IBankClient,用来根据不用的用户类型, 直接返回一个对用的处理银行业务的IBankProcess接口实例;
- 这种修改虽然解决了很多if和switch的问题,但是本质,并没有根据用户的类型,自动实现方法的调用,这里需要反射和泛型来完成;
//不同业务用户来银行办理不同的业务
//分析经常发生变化的业务:①银行处理业务 ②User用户
//不经常变动:BankStuff 银行员工
public class Program
{public static void Main(string[] args){//创建银行员工BankStuff bankStuff = new BankStuff();//创建一个存钱用户的操作IBankClient bankClient = new HandleSave();//用户办理业务bankStuff.Handle(bankClient);}
}//3.创建IBankClient接口,根据用户传来的业务,返回对应银行处理业务
//封装变化:变化的是传来的不同业务
public interface IBankClient
{IBankProcess GetBankProcess();
}public class HandleSave : IBankClient
{public IBankProcess GetBankProcess(){IBankProcess bankProcess = new SaveMoney();return bankProcess;}
}public class HandleGet : IBankClient
{public IBankProcess GetBankProcess(){IBankProcess bankProcess = new