设计模式之设计原则(下)
好久没有写博客啦,因最近在忙于弄自己的一个网站,一直没有时间写了,在这里跟广大园友说声抱歉,今天也正好是中秋节,在这里祝大家节日快乐!废话少说,接续上节的继续写下去。
依赖倒置原则(Dependence Inversion Principle),简称DIP:他的核心思想就是在进行业务设计时,高层模块不应该依赖于底层模块,两者应该依赖与抽象,抽象而不依赖于具体实现,具体实现应该依赖与抽象,这样会使代码变得更稳定,从而大大提高了程序应对业务变化的能力。
我们来看一下一个例子来更深刻的理解一下上面的核心思想:
1 public class Car 2 3 { 4 5 public string CarName; 6 7 8 9 public Car(string carname) 10 11 { 12 13 this.CarName = carname; 14 15 } 16 17 public void 驾驶() 18 19 { 20 21 Console.WriteLine(CarName + ":驾驶"); 22 23 } 24 25 26 27 } 28 29 30 31 public class Person 32 33 { 34 35 public void drive() 36 37 { 38 39 Car bmw=new Car("BMW"); 40 41 bmw.驾驶(); 42 43 } 44 45 }
从上面的例子看一下能发现Person类依赖与Car类,这样耦合度高,这样的话比如说Car类发生变化时很容易出现问题,比如说哪天这个Person类不想开汽车了想开火车或者飞机时怎么办,那我们可以改造一下上面的类,Person类不依赖于Car这个具体实现,我们要依赖抽象,依赖与交通工具,我们看看代码:
1 //交通工具才抽象 2 3 public interface IVehicle 4 5 { 6 7 void 驾驶(); 8 9 } 10 11 //汽车 12 13 public class Car : IVehicle 14 15 { 16 17 public string CarName; 18 19 20 21 public Car(string carname) 22 23 { 24 25 this.CarName = carname; 26 27 } 28 29 public void 驾驶() 30 31 { 32 33 Console.WriteLine(CarName + ":驾驶"); 34 35 } 36 37 38 39 } 40 41 //飞机 42 43 public class Plane : IVehicle 44 45 { 46 47 public string PlaneName; 48 49 50 51 public Plane(string carname) 52 53 { 54 55 this.PlaneName = carname; 56 57 } 58 59 public void 驾驶() 60 61 { 62 63 Console.WriteLine(PlaneName + ":驾驶"); 64 65 } 66 67 68 69 } 70 71 //火车 72 73 public class Train : IVehicle 74 75 { 76 77 public string TrainName; 78 79 80 81 public Train(string carname) 82 83 { 84 85 this.TrainName = carname; 86 87 } 88 89 public void 驾驶() 90 91 { 92 93 Console.WriteLine(TrainName + ":驾驶"); 94 95 } 96 97 98 99 } 100 101 public class Person 102 103 { 104 105 private IVehicle machine = null; 106 107 public Person(IVehicle _vehicle) 108 109 { 110 111 machine = _vehicle; 112 113 } 114 115 public void drive() 116 117 { 118 119 machine.驾驶(); 120 121 } 122 123 }
类图如下:
客户端调用代码:
1 Person person1=new Person(new Car("宝马")); 2 3 person1.drive(); 4 5 Person person2=new Person(new Plane("飞机")); 6 7 person2.drive(); 8 9 Person person3=new Person(new Train("火车")); 10 11 person3.drive(); 12 13 Console.ReadLine();
输出结果如下:
从以上代码可以看出Person类的驾驶方法来说不需要依赖具体的交通工具,只依赖抽象,具体的哪一个交通工具是从外部传入的。这样其实就是抽象编码。也是依赖倒置的有点。
组合优于继承:他的核心思想就是组合比继承更大的灵活性和稳定结构。
为什么怎么说呢,我们来看看他们各自的优缺点:
继承优点:
1)新的实现很容易,因为大部分是继承而来的。
2)很容易修改和扩展已有的实现
继承的缺点:
1)打破了封装,因为基类想子类暴露额具体的实现细节。
2)白盒重用,因为基类的内部细节通常对子类是可见的。
3)当父类发生改变时子类也做出相应的改变。
4)不能在运行时修改由父类继承来的实现。
组合优点:
1)被包含对象通过包含他们的类来访问
2)黑盒重用,因为被包含对象的内部细节是不可见的
3)很好的封装
4)每一个类都专注于一个任务
5)通过获得和被包含对象的类型相同的对象引用,可以在运行时动态定义组合的方式
组合缺点:
1)系统可能会包含更过的对象
2)为了使组合时可以使用不同的对象,必须小心的定义接口。