目录
前言
最近在读《敏捷软件开发 原则、模式与实践》,里面提到了几大设计原则,于是想复习下,并且用C#把文中代码重新写一遍
依赖倒置原则(DIP)
概念
高层模块不应该依赖于低层模块。二者都应该依赖于抽象。
一个简单的例子
违反DIP的例子
// Button类(高层策略)直接依赖具体类
public class Button {
private Lamp itsLamp; // 糟糕:高层依赖低层
public void Poll() {
if (/* 被按下 */) itsLamp.TurnOn();
else itsLamp.TurnOff();
}
}
// Lamp类(低层细节)
public class Lamp {
public void TurnOn() { /* 开灯 */ }
public void TurnOff() { /* 关灯 */ }
}
符合DIP的改进设计
// 抽象接口由客户(Button)拥有,定义在高层模块
public interface ISwitchableDevice {
void TurnOn();
void TurnOff();
}
// Lamp实现抽象接口(细节依赖抽象)
public class Lamp : ISwitchableDevice {
public void TurnOn() { /* 开灯 */ }
public void TurnOff() { /* 关灯 */ }
}
// Button只依赖抽象
public class Button {
private ISwitchableDevice device; // 依赖抽象
public Button(ISwitchableDevice device) => this.device = device;
public void Poll() {
if (/* 被按下 */) device.TurnOn();
else device.TurnOff();
}
}
// 现在可以轻松扩展
public class Motor : ISwitchableDevice { /* 实现 */ }
动态多态 vs 静态多态
考虑一个控制熔炉调节器的软件。该软件可以从一个IO通道中读取当前的温度,并通过向另一个IO通道发送命令来指示熔炉的开或者关。
违反DIP的原始设计
public class FurnaceController {
private const int THERM_PORT = 0x86;
private const int FURN_PORT = 0x87;
public void Regulate(double min, double max) {
while (true) {
while (ReadHardware(THERM_PORT) > min) Wait(1);
WriteHardware(FURN_PORT, 1); // 打开
while (ReadHardware(THERM_PORT) < max) Wait(1);
WriteHardware(FURN_PORT, 0); // 关闭
}
}
}
改进方案A:动态多态性(接口)
运行时动态替换实现,支持模拟器测试。
// 抽象接口
public interface IThermometer { double Read(); }
public interface IHeater { void Engage(); void Disengage(); }
// 高层策略依赖抽象
public class Regulator {
public void Regulate(IThermometer t, IHeater h, double min, double max) {
while (true) {
while (t.Read() > min) Wait(1);
h.Engage();
while (t.Read() < max) Wait(1);
h.Disengage();
}
}
}
// 具体实现(细节依赖抽象)
public class HardwareThermometer : IThermometer {
public double Read() => /* 读取硬件0x86 */ 0.0;
}
public class FurnaceHeater : IHeater {
public void Engage() => /* 操作硬件0x87 */ ;
public void Disengage() => /* ... */ ;
}
改进方案B:静态多态性(泛型)
性能更高,但类型在编译时固定,更换实现需重新编译。
// 通过泛型实现编译时多态,无需虚函数开销
public class Regulator<TTherm, THeater>
where TTherm : IThermometer, new()
where THeater : IHeater, new() {
private TTherm thermometer = new();
private THeater heater = new();
public void Regulate(double min, double max) {
while (true) {
while (thermometer.Read() > min) Wait(1);
heater.Engage();
while (thermometer.Read() < max) Wait(1);
heater.Disengage();
}
}
}
// 使用
var regulator = new Regulator<HardwareThermometer, FurnaceHeater>();
regulator.Regulate(20, 25);
参考文献
敏捷软件开发 原则、模式与实践

324

被折叠的 条评论
为什么被折叠?



