1 里氏代换原则OpenEIM从开-闭原则中可以看出来面向对象的重要原则是创建抽象化,并从抽象化导出具体化。具 体化可以给出不同的版本,每一版本都给出不同的实现。里氏代换原则从另一个侧面描述 抽象化和具体化,里氏代换原则表明:一个软件如果使用的是一个基类的话,那么一定适 用于其子类,而且它根本不可能察觉出基类对象和子类对象的区别;必须指出,这个原则 反过来不一定成立,即一个软件实体使用的是一个子类的话,那么它不一定适用于基类。
2 模式中的里氏代换原则
2.1 策略模代策略模式讲的是:如果有一组算法,那么就将每一个算法封装起来,使它们可以互换。 封装的概念不难理解,而使算法可以互换大,则需要将具体策略角色放到一个类型等级 结构中,使它们拥有共同的接口,这种互换性依赖的是里氏代换原则。从策略模式uml中 可以看出,客户端依赖于基类类型,而真实类型是具体的策略类(子类),这是具体策略 角色可以即插即用的关键。
策略模式
2.2 合成模式合成模式通过使用树结构描述整体与部分的关系,从而可以将叶子元素和复合元素同等 看待,由于叶子元素和复合元素都是抽象角色的子类,因此两者都可以替代抽象角色出 现的任何地方,显然,里氏代换原则是合成模式能够成立的基础。
合成模式
2.3 代理模式代理模式给某一对象提供一个代理对象(Proxy),并由代理对象控制原对象 (RealSubject)的引用,代理模式能够成立的关键,在于代理对象和原对象都是抽象角色 (Subject)的子类,客户端只知道抽象角色,而代理对象可以代替抽象角色出现在任何地 方,而将原对象隐藏在幕后。
代理模式
3 如何继承
3.1 不要从具体类继承只要有可能,不要从具体类继承,如图,给出了一个继承形成的等级结构例子,可以看 出,所有子类都是从接口或抽象类继承,具体类没有子类。换言之,在一个继承关系形 成的等级结构里,树叶节点均应是具体类,而树枝节点均应是接口或抽象类。
不从具体类继承
3.2 避免错误继承抽象化(包括接口和抽象类)通常代表一个抽象概念,它提供一个继承的出发点,而具体类 则不同,具体类可以实例化,应当给出一个有商业逻辑实现的对象模板,不应当做为超类。 子类应当扩展超类的责任,而不是置换或撤消超类的责任。如果有两个具体类有继承关 系,通常子类需要将继承自超类的责任取消或置换后才能使用,很可能这个子类根本就不 是那个超类的子类,这样的设计可以优化。
将狗设计成猫的子类,如图所示,猫有上树的能力,狗没有,为了继承关系成立,只好将 猫上树的能力取消掉,这个关系显然是错误的。正确的继承关系是引入一个抽象类,在这 里就是动物类,两个具体类设计成抽象类的子类。
正确继承