//最后,我们来看客户端的调用: public void DecriptionTheAnimal(Animal animal) { if (typeof(animal) is Cat) { Cat cat = (Cat)animal; Cat.Decription(); Cat.Mew(); } else if (typeof(animal) is Dog) { Dog dog = (Dog)animal; Dog.Decription(); Dog.Bark(); } } 通过上面的代码,我们可以看到虽然客户端的依赖是对抽象的依赖,但依然这个设计的扩展性不好,运行期绑定没有实现。phpma开源 是什么原因呢?其实就是因为不满足里氏替换原则,子类如Cat有Mew()方法父类根本没有,Dog类有Bark()方法父类也没有,两个子类都不能替换父类。这样导致了系统的扩展性不好和没有实现运行期内绑定。 现在看来,一个系统或子系统要拥有良好的扩展性和实现运行期内绑定,有两个必要条件:第一是依赖倒置原则;第二是里氏替换原则。这两个原则缺一不可。
我们知道,在我们的大多数的模式中,我们都有一个共同的接口,然后子类和扩展类都去实现该接口。 下面是一段原始代码: if(action.Equals(“add”)) { //do add action } else if(action.Equals(“view”)) { //do view action } else if(action.Equals(“delete”)) { //do delete action } else if(action.Equals(“modify”)) { //do modify action } 我们首先想到的是把这些动作分离出来,就可能写出如下的代码:phpma开源 public class AddAction { public void add() { //do add action } } public class ViewAction { public void view() { //do view action } } public class deleteAction { public void delete() { //do delete action } } public class ModifyAction { public void modify() { //do modify action } } 我们可以看到,这样代码将各个行为独立出来,满足了单一职责原则,但这远远不够,因为它不满足依赖颠倒原则和里氏替换原则。phpma开源 下面我们来看看命令模式对该问题的解决方法: public interface Action { public void doAction(); } //然后是各个实现: public class AddAction : Action { public void doAction() { //do add action } } public class ViewAction : Action { public void doAction() { //do view action } } public class deleteAction : Action { public void doAction() { //do delete action } } public class ModifyAction : Action { public void doAction() { //do modify action } } //这样,客户端的调用大概如下: public void execute(Action action) { action.doAction(); } 看,上面的客户端代码再也没有出现过typeof这样的语句,扩展性良好,也有了运行期内绑定的优点。