C#设计原则

server/2024/11/14 6:06:29/

文章目录

  • 项目地址
  • 一、开放封闭原则
    • 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("处理用户转账");}
}
  • 问题:
    1. BankProcess不符合单一职责原则,修改三个方法的时候,都会影响这个类
    2. 在BankStuff里全是case,如果代码里全是case,肯定不符合设计模式

1.2 将BankProcess的实现改为接口

  1. 如何判断一个类设计的好坏就是:当你要修改类里面重要的方法的时候,不会影响到方法的执行!例如:我们对BankProcess里的取钱方法进行修改时候,整个BankProcess类是没办法使用的,只能当我们把全部功能改好了之后,这个类才能使用;
  2. 就类似于修路,路的主要功能有人行道和车行道路,我们在修人行道的时候,不能影响到车行道的车辆通行,才是一个好类的设计思想。
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类

  1. 用过抽象或者接口,对变化进行封装;
  2. 这里经常发生变化的就是传入的用户类型;所以,创建了一个IBankClient,用来根据不用的用户类型, 直接返回一个对用的处理银行业务的IBankProcess接口实例;
  3. 这种修改虽然解决了很多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 

http://www.ppmy.cn/server/141781.html

相关文章

arcgis for js实现FeatureLayer图层弹窗展示所有field字段方式二

效果和说明 feature图层中的矢量要素包含很多的属性,在点击要素时popupTemplate弹窗显示所有field字段值 上一篇文章提到对field值进行转义,在研究时发现新的弹窗展示所有字段的另一种方式,更加便捷,且样式可自定义 实现代码 &l…

LinkedList和单双链表。

java中提供了双向链表的动态数据结构 --- LinkedList,它同时也实现了List接口,可以当作普通的列表来使用。也可以自定义实现链表。 单向链表:一个节点本节点数据下个节点地址 给定两个有序链表的头指针head1和head2,打印两个链表…

测试实项中的偶必现难测bug--苹果支付丢单问题

问题描述: app支付后,由于某种原因(可能是网络、流量不稳定、或者用户快速频繁操作。。。)会造成一定概率性的回调苹果支付结果失败的情况出现,表现的直观现象就是客户反馈已经支付了,包括苹果支付也是有记录,但是我们的后台显示的是已取消状态的订单 验证难点:测试和…

【Linux进程篇5】理解分析更改->进程优先级❤️

-------------------------------------------------------------------------------------------------------------------------------- 每日鸡汤:无需匆忙,不要将就,缘分到了,就一定会在一起。 -----------------------------…

以太坊系地址衍生算法分层确定性生成逻辑

文章目录 一、前言1.1 衍生算法生成的私钥1.2 随机生成的私钥二、私钥生成及私钥提取2.1 golang如何使用衍生算法生成私钥,然后为用户生成地址2.1.1 实现步骤2.1.2 golang代码示例2.1.3 代码说明2.2 地址交易时,如何提取地址私钥2.2.1 私钥恢复说明2.2.2 golang代码通过助记词…

k8s拓扑域 :topologyKey

主要用于定义Pod亲和性或反亲和性规则中的拓扑域,从而控制Pod在集群中的调度。 参数描述:仅支持在工作负载亲和/工作负载反亲和调度策略中使用。先圈定拓扑域(topologyKey)指定的范围,然后再选择策略定义的内容。 to…

详解二叉树(上)---堆

目录 一、树 1.2 树的相关术语 1.3 树的表示方法 二、二叉树 2.1 概念与结构 2.2 二叉树的特殊形式 2.3 二叉树的性质 2.4 二叉树的存储结构 1.顺序结构 2.链式结构 2.5 实现顺序结构二叉树(堆) 1.堆的概念 2. 堆的性质 3.堆的实现 三、全…

MySQL Workbench导入数据比mysql命令行慢

1.数据量 包含2812979条数据的csv文件 2.myql命令行用LOAD DATA INFILE命令导入 耗时1分钟13秒 3.用MySQL Workbench导入 从第一天晚上22点到次日下午16点才导入了45万条数据 4.原因 MySQL Workbench导入csv数据是使用自带的python和一系列的python代码,而mys…