设计原则(一):开放封闭原则

star2017 1年前 ⋅ 708 阅读

抽象

开-闭原则的关键在于抽象化,抽象层封装与商业逻辑有关的重要行为,这些行为的具体实现由实现层给出。

抽象层不能再修改,但允许扩展系统的实现层,这样系统就有一定的稳定性和延续性。

抽象的行为由具体实现层提供,这样就提供了新的行为,满足对软件的新需求,易于扩展且具有一定的灵活性和适应性。

开-闭 原则可以看出 面向对象设计 的重要原则是创建抽象化,并且从抽象化导出具体化。具体化可以给出不同的版本,每一个版本都给出不同的实现。

对可变性的封装

开-闭原则如果从另一个角度来讲述,就是所谓的 对可变性的封装原则,讲的是找到一个系统的可变因素,将之封装起来。

对可变性的封装原则:与通常将焦点放在什么会导致设计改变的思考方式正好相反,这一思路考虑的不是什么会导致设计改变。而是考虑你允许什么发生变化,而不让这一变化导致重新设计

对可变性的封装原则意味着两点:

  1. 一种可变性不应当散落在代码的很多角落里,而应当被封装到一个对象里面。同一种可变性的不同表象意味着同一个继承等级结构中的具体子类。

    继承应当被看做是封装变化的方法,而不应该被认为是从一般的对象生成特殊的对象的方法。

  2. 一种可变性不应当与另一种可变性混合在一起,表现上是继承不该超过两层,否则就意味着将两种不同的可变性混合在了一起。

【GOF95】指出,对可变性的封装原则 实际上是设计模式的主题。换句话说,所有的设计模式都是对不同的可变性的封培训,从而使系统在不同的角度上达到 开-闭原则的要求。

与其它原则的关系

  1. 里氏替换原则:指任何基类可以出现的地方,子类一定可以出现。

    里氏替换原则是对 开-闭 原则的补充。实现 开-闭 原则的关键步骤是抽象化。而基类与子类的继承关系就是抽象化的具体体现,所以里氏替换原则是对实现抽象化的具体步骤的规范。

    一般而言,违返里氏替换原则,也违背 开-闭 原则,反过来并不一定成功。

  2. 依赖倒置原则:指要依赖于抽象,不要依赖于实现。

    看上去 依赖倒置 原则与 开-闭原则 很类似,实现上,他们之间是 目标手段 之间的关系。开-闭原则是目标,而达到这一目标的手段是 依赖倒置原则

    换句话说,要想实现 开-闭原则,就应当坚持 依赖倒置原则。违反依赖倒置原则,就不可达到 开-闭 原则的要求。

  3. 合成/聚合复用原则:指的是要尽量使用 合成/聚合,而不是继承关系达到复用的目的。,

    合成/聚合复用原则是与 里氏替换原则相辅相成的,两者又都是对实现 开-闭原则的具体步骤的规范。前者要求设计师首先考虑 合成/聚合关系,后者要求在使用继承关系时,必须确定这个关系是符合一定条件的。

    遵守 合成/聚合 复用原则是实现 开-闭 原则的必要条件;违反这一原则就无法使系统实现 开-闭 原则这一目标。

  4. 迪米特法则:又叫最少知识原则,指一个软件实体应当于尽可能少的其他实体发生相互作用

    即尽可能保持模块相对独立,在需要修改时不会将修改的压力传递给其他的模块。

    也就是说,一个遵守迪米特原则设计出来的系统在功能需要扩展时,会相对更容易地做到对修改的关闭。也就是说,迪米特法则是一条通向 开-闭 原则的道路。

  5. 接口隔离原则:指应当为客户端提供尽可能少的单独的接口,而不是指供大的总接口。

    接口隔离原则 与 广义的迪米特法则 都是对一个软件实体与其他的软件实体的通信的限制。

    广义的迪米特法则要求尽可能限制通信的宽度和深度。接口隔离原则所限制的是通信的宽度,也就是说通信应当尽可能地窄。

    遵特接口隔离原则与迪米特法则,会使一个软件系统在功能扩展的过程中,不会将修改的压力传递到其他的对。

在其它设计模式中的体现

开-闭 原则要求系统允许新的功能加入系统中,而无需对现有代码进行修改。

  • 简单工厂模式:对产品的消费角色是成立的,但对于工厂角色是不成立的。每次增加一个新的增品,都需要修改工厂角色。但是产品的消费者则可以避免修改。

  • 工厂方法模式:具体工厂类都有共同的接口,它们生产出很多处于一个等级结构中的产品对象。该模式允许向系统加入新的产品类型,而不必修改已有的代码,只需再加入一个相应的新的具体工厂类即可,即完全支持 开-闭 原则。

  • 抽象工厂模式:抽象工厂模式封装了产品对象家族的可变化性,从而一方面可以使系统动态地决定将哪一个产品族的产品实例化,另一方面可以在新的产品对象引进到已有的系统中时不必修改已有的代码。即该模式可以维持系统的 开-闭 性。

  • 建造模式:建造模式封装了建造一个内部结构的产品对象的过程,因此是向产品内部表象的改变开放的。

  • 桥接模式:桥接模式是对可变性的封装原则的极好例子。在桥接模式中,具体实现类代表不同的实现逻辑,但是所有的具体实现类又有共同的接口。新的实现逻辑可以通过创建新的具体实现类加入到系统中。

  • 门面模式:假设一个系统与另一个子系统耦合在一起,后来又必须换成另一个子系统,那么门面模式便可以发挥门面模式和适配器模式两种作用,将新的子系统仍然与本系统耦合在一起。使用门面模式便可以改变子系统内部功能而不影响到客户端。

  • 调停者模式:调停者模式使用一个调停者对象协调各个同事对象的相互作用,这些同事对象不再发生直接的相互作用。调停者模式类图类似于一个星型网络图。

    使用该模式,如果有新的同事对象添加到系统中来的时候,这些已有的同事对象都不会受到任何影响,但调停者本身却需要修改。即 调停者模式以一种不完美的方式支持 开-闭 原则。

  • 访问者模式:访问者模式使得在节点中加入新的方法变得很容易,仅仅需要在一个新的访问者类中加入此方法就可以了,但是访问者模式不能很好地处理增加新节点的情况。也就是说,访问者模式提供了倾斜的可扩展性设计:方法集合的可扩展性和类集合的不可扩展性。

    也就是说,访问者模式的使用可以使一个节点系统对方法集合的扩展开放。

  • 迭代子模式:迭代子模式将访问聚集元素的逻辑封装起来,并且使它独立于聚集对象的封装。这就提供了聚集逻辑与迭代逻辑独立演变的空间,使系统可以在无需修改消费迭代子的客户端的情况下,对聚集对象的内部结构进行功能扩展。

更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: