单一职责原则(Single Responsibility Principle, SRP)
什么是单一职责原则
一个类只负责一件事情
一个模块的所有功能都应该高度相关、围绕同一职责
当需求变更时,应只影响到一个类,而不是同时影响多个不相关功能的类
为什么要遵守SRP
- 降低耦合
当一个类承担多种职责时,一个职责的变化可能会影响到其他职责。
- 提高可维护性
变更影响面更小,维护更轻松。
- 提高可测试性
单一职责的类更容易编写单元测试。
- 增强可读性
结构更清晰,让别人一眼就知道这个类的目的。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class TelPhone { public void Dial(string phoneNumber) { Console.WriteLine("给 " + phoneNumber+" 打电话"); }
public void HangUp(string phoneNumber) { Console.WriteLine("挂断 " + phoneNumber+" 的电话"); }
public void SendMessage(string phoneNumber, string message) { Console.WriteLine("给 " + phoneNumber + " 发送消息: " + message); }
public void ReceiveMessage(string phoneNumber, string message) { Console.WriteLine(phoneNumber + " 收到消息: " + message); } }
|
变化一:内部的变化,如果TelPhone内部的方法,任意之一,发生了改变,那会需要修改TelPhone,不符合单一职责原则
变化二:外部的变化,如果TelPhone要添加新的方法,也需要修改TelPhone
只有添加的时候才会触发这个类的改变,其他的修改都不要触发这个类的改变
优化:
给每个方法,都提炼成一个接口,抽象成一种能力,然后分别鞋类,去实现接口,最终在TelPhone中,只进行调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| public interface IDidl { void Dial(string phoneNumber); }
public interface IHangUp { void HangUp(string phoneNumber); }
public interface ISendMessage { void SendMessage(string phoneNumber, string message); }
public interface IReceiveMessage { void ReceiveMessage(string phoneNumber, string message); }
public class Dialclass : IDidl { public void Dial(string phoneNumber) { Console.WriteLine("给 " + phoneNumber + " 打电话"); } } public class HangUpclass : IHangUp { public void HangUp(string phoneNumber) { Console.WriteLine("挂断 " + phoneNumber + " 的电话"); } } public class SendMessageclass : ISendMessage { public void SendMessage(string phoneNumber, string message) { Console.WriteLine("给 " + phoneNumber + " 发送消息: " + message); } } public class ReceiveMessageclass : IReceiveMessage { public void ReceiveMessage(string phoneNumber, string message) { Console.WriteLine(phoneNumber + " 收到消息: " + message); } }
public class TelPhone { private IDidl _dial; private IHangUp _hangUp; private ISendMessage _sendMessage; private IReceiveMessage _receiveMessage; public TelPhone(IDidl dial, IHangUp hangUp, ISendMessage sendMessage, IReceiveMessage receiveMessage) { _dial = dial; _hangUp = hangUp; _sendMessage = sendMessage; _receiveMessage = receiveMessage; } public void Dial(string phoneNumber) { _dial.Dial(phoneNumber); }
public void HangUp(string phoneNumber) { _hangUp.HangUp(phoneNumber); }
public void SendMessage(string phoneNumber, string message) { _sendMessage.SendMessage(phoneNumber, message); }
public void ReceiveMessage(string phoneNumber, string message) { _receiveMessage.ReceiveMessage(phoneNumber, message); } }
|
开放封闭原则
什么是开放封闭原则
当需求变更时,应该 通过扩展新代码 来应对
而不是修改已稳定上线的旧代码
为什么需要 OCP
- 减少风险
改旧代码容易引入 Bug。扩展新代码更安全。
- 提高可维护性
避免在核心流程中不停加 if-else、switch-case。
- 提高可扩展性
新增需求只需要新增类或策略,而不是动旧逻辑。
示例:
对象1:用户:属性:记录不同类型的用户(存钱、取钱、转账)
对象2:银行柜员:帮助我们用户处理不同的需求
对象3:银行业务系统:处理存钱、取钱、转账等需求的操作系统
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| public class Bank { public static void Bankclas(string[] args) { BankClient client = new BankClient(); client.BankType = "存款"; BankStuff stuff = new BankStuff(new BankProcess()); stuff.HandleProcess(client); } }
public class BankClient { public string? BankType{get;set;} }
public class BankStuff { private BankProcess _bankProcess; public BankStuff(BankProcess bankProcess) { _bankProcess = bankProcess; } public void HandleProcess(BankClient client) { switch (client.BankType) { case "存款": _bankProcess.Deposit(); break; case "取款": _bankProcess.Withdraw(); break; case "转账": _bankProcess.Transfer(); break; default: Console.WriteLine("无效的操作"); break; } } }
public class BankProcess { public void Deposit() { Console.WriteLine("存款"); } public void Withdraw() { Console.WriteLine("取款"); } public void Transfer() { Console.WriteLine("转账"); } }
|
此代码并没有实现单一原则,且开放封闭原则,只开放并没有封闭(一个软件实体应该对扩展开放,对修改封闭。即软件实体应尽量在不修改原有代码的情况下进行扩展)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| public class Bank { public static void Bankclas(string[] args) { IBankClient client = new TransferClient(); BankStuff ctx = new BankStuff(); ctx.HandleProcess(client); } }
public class BankClient { public string? BankType{get;set;} }
public class BankStuff { private IBankProcess? _bankprocess;
public void HandleProcess(IBankClient client) { _bankprocess = client.GetBankProcess(); _bankprocess.BankProcess(); } }
public interface IBankClient { IBankProcess GetBankProcess(); }
public class DepositClient : IBankClient { public IBankProcess GetBankProcess() { return new Deposit(); } }
public class WithdrawClient : IBankClient { public IBankProcess GetBankProcess() { return new Withdraw(); } }
public class TransferClient : IBankClient { public IBankProcess GetBankProcess() { return new Transfer(); } }
public interface IBankProcess { void BankProcess(); }
public class Deposit : IBankProcess { public void BankProcess() { Console.WriteLine("存款"); } }
public class Withdraw : IBankProcess { public void BankProcess() { Console.WriteLine("取款"); } }
public class Transfer : IBankProcess { public void BankProcess() { Console.WriteLine("转账"); } }
|