0x01、设计模式原则 —— 单一职责原则
概念
对类来说的,一个类应该只负责一项职责。(记住)
假如:类A负责两个不同职责:职责1,职责2。当职责1需求变更而改变类A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1, A2(即将类A的两个职责分解为A1类和A2类);
代码解说
先看如下代码:
Vehicle _vehicle = new Vehicle(); _vehicle.Run("汽车"); _vehicle.Run("飞机"); _vehicle.Run("轮船"); // 交通工具类 class Vehicle{ public void Run(string vehicle){ Console.WriteLine($"{vehicle}在公路上运行...."); } }
Vehicle类的Run方法只管公路上的,而传递过来的参数除了汽车,还有飞机和轮船,难道飞机和轮船都在公路上运行吗?显然,这里我们把 Vehicle类 当做三个职责来使用;
即:交通工具类Vehicle ,已经违反了 单一职责原则;
上面说了,单一职责原则 是 一个类应该只负责一个职责,那么我们将改成下面这样:
CarVehicle _vehicle = new CarVehicle(); _vehicle.Run("小汽车"); AirVehicle airVehicle = new AirVehicle(); airVehicle.Run("飞机"); WaterVehicle waterVehicle = new WaterVehicle(); waterVehicle.Run("轮船"); // 陆上交通工具 class CarVehicle{ public void Run(string vehicle){ Console.WriteLine($"{vehicle}在公路上运行...."); } } // 水上交通工具 class WaterVehicle{ public void Run(string vehicle){ Console.WriteLine($"{vehicle}在水上运行...."); } } // 天上交通工具 class AirVehicle{ public void Run(string vehicle){ Console.WriteLine($"{vehicle}在天上运行...."); } }
上面代码,就遵守了单一职责原则;
但是这样没有问题吗?有,当发生修改时,我们除了要修改每一个交通工具类,还需要修改 创建这些类的地方;
改进:
Vehicle _vehicle = new Vehicle(); _vehicle.RunAtRound("小汽车"); _vehicle.RunAtWater("轮船"); _vehicle.RunAtAir("飞机"); // 1.这种修改方法没有对原来的类做大的修改,只是增加方法 // 2.这里虽然没有在类这个级别上遵守单一职责原则,但是在方法级别上,仍然是遵守单一职责 class Vehicle { public void RunAtRound(string vehicle){ Console.WriteLine($"{vehicle}在公路上运行...."); } public void RunAtWater(string vehicle){ Console.WriteLine($"{vehicle}在水上运行...."); } public void RunAtAir(string vehicle){ Console.WriteLine($"{vehicle}在天上运行...."); } }
上面代码并没有用 类 来分解,我们只在交通工具类中添加了方法,即使这样子,也是遵守了 单一职责原则 的,只是层面是在方法上分离了职责,而不是在类上;
即:虽然没有在类这个级别上遵守单一职贵原则,但是在方法级别上,仍然是遵守单一职贵 !
总结
- 类分解,可能成本较高
- 不在类级别上“单一职责”,往下沉,在方法级别上“单一职责”
补充
单一职责:
- 降低了类的复杂度,因为一个类只负责一项职责。(上面示例没体现出来,而在大项目中尤为明显)
- 提高类的可读性,可维护性
- 降低变更引起的风险
- 通常情况下, 我们应当遵守单一职责原则,如果逻辑足够简单、类中方法数量足够少,也是可以在代码级违反单一职责原则,在方法级别保持单一职责原则(上面改进的代码就是这种)
提醒:单一职责原则,即一个类只负责一项职责(但是千万不要理解为:一个类只有一个方法 这种想法)
ASP.NET Core 中,单一职责体现在:每一个控制器里面都是负责一项职责的,比如 用户控制器类负责用户、订单控制器类负责订单、文章控制器类负责文章 等。。。
本章简单吧?继续下一个原则:接口隔离原则