动机
一个设计良好的应用程序应该充分考虑到开发和维护阶段需求的频繁变化,通常情况下,添加一个新的功能需要做出很多修改,我们应该使对已有代码的修改最小化,因为他们已经经过了测试。对现有代码做出修改将会以一种不可预料的方式影响它们的已有功能。
开放-关闭原则 (以下简称开闭原则)
开-闭原则:
一个软件实体应该对扩展开发,对修改关闭。
开闭原则是说我们应该努力设计不需要修改的模块。在扩展系统的行为时,我们只需要添加新的代码,而不需要修改已有的代码。一般可以通过添加新的子类和重写父类的方法来实现。
满足开闭原则的模块符合下面两个标准:
- 对扩展开放 ------- 模块的行为可以被扩展从而满足新的需求。
- 对修改关闭 ------- 不允许修改模块的源代码。(或者尽量使修改最小化)
这两个标准看似相互矛盾的,那么我们怎么实现他们呢?
怎样实现开闭原则
要想使一个软件系统的所有模块都满足开闭原则是不太现实的,不过我们应该努力使大部分模块满足开闭原则。开闭原则是面向对象设计的核心,满足该原则可以达到最大限度的复用和可维护性。
实例
考虑下面某个类的方法:
public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i=0; i<parts.length; i++) {
total += parts[i].getPrice();
}
return total;
}
上面函数的功能是计算给定的零件数组中所有零件价格的总和,如果Part是一个基类或者接口,那我们就可以利用多态的特性,当有新的零件被添加进来时不需要修改该函数的代码。这样它就可以满足开闭原则。
但是如果我们的会计部门规定当计算主板和内存的价格时,需要添加一些额外的费用,请看下面的代码:
public double totalPrice(Part[] parts) {
double total = 0.0;
for (int i=0; i<parts.length; i++) {
if (parts[i] instanceof Motherboard)
total += (1.45 * parts[i].getPrice());
else if (parts[i] instanceof Memory)
total += (1.27 * parts[i].getPrice());
else
total += parts[i].getPrice();
}
return total;
}
现在它还符合开闭原则吗?不!每次会计部门发布一个新的价格政策时,我们都需要修改totalPrice()方法!它对修改不是关闭的,显然,价格政策的改变意味着我们必须修改某处的代码,那么我们应该怎么做呢?为了使用我们第一个版本的totalPrice()方法,我们需要把Part的getPrice()方法的价格政策包含进来。
下面是Part和ConcretePrat类:
// Class Part is the superclass for all parts.
public class Part {
private double price;
public Part(double price) (this.price = price;}
public void setPrice(double price) {this.price = price;}
public double getPrice() {return price;}
}
// Class ConcretePart implements a part for sale.
// Pricing policy explicit here!
public class ConcretePart extends Part {
public double getPrice() {
// return (1.45 * price); //Premium
return (0.90 * price); //Labor Day Sale
}
}
但是,现在如果价格政策改变,我们必须修改Part的子类,一个更好的方法是建立一个PricePolicy类,它可以为我们提供不同的价格政策:
/**
* Class PricePolicy implements a given price policy.
*/
public class PricePolicy {
private double factor;
public PricePolicy (double factor) {
this.factor = factor;
}
public double getPrice(double price) {return price * factor;}
}
使用这种方法,我们可以在运行时动态的设置Part对象所引用的PricePoilcy对象,在实际的程序中,零件的价格和相关的PricePolicy可以从数据库中获取。
总结
像许多其他原则一样,开闭原则只是面向对象设计的一个原则,实现一个灵活的设计需要额外的时间和努力,引入新的抽象层会增加代码的复杂性。因此,该原则适用于那些需求会经常发生变化的系统。有许多设计模式可以帮助我们扩展功能而不需要修改代码。例如,装饰模式等。
分享到:
相关推荐
面向对象的类的设计原则,本人认为对于学习面向对象的设计很有用。开放关闭原则
一个类图的类名是必须的 第2页/共30页 Java面向对象程序设计杨晓燕面向对象基本原则和模式全文共30页,当前为第2页。 类的UML图 注意:属性和方法之前附加的可见性修饰符, "+"表示public,"-"表示private,"#"表示...
面向对象的11个设计原则 SOLID原则 单一职责原则(The Single Responsibility Principle) 开放/关闭原则(The Open Closed Principle) 里氏替换原则(The Liskov Substitution Principle) 依赖倒置原则(The Dependency ...
面向对象程序设计六大原则 一、“开-闭”原则(Open-Closed Principle,OCP) 1.1“开-闭”原则的定义及优点 1)定义:一个软件实体应当对扩展开放,对修改关闭( Software entities should be open for extension,but...
1.单一职责原则: 不要存在多于一个导致类变更的原因 2.里氏替换法则:子类可以扩展父类的功能,但不能改变父类原有的功能 3.依赖倒置原则:面向接口编程 ...而开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。
35面向对象设计原则 54 1、找出应用中可能需求变化的代码,把它们独立出来,不要和那些需求不变化的的代码混在一起 54 2、针对接口编程,而不要针对实现类编程 54 3、多用组合,少用继承(包含实现) 54 4、为了交互...
本文我们要谈的七大原则,即:单一职责,里氏替换,迪米特法则,依赖倒转,接口隔离,合成/聚合原则,开放-封闭 。 1. 开闭原则(Open-Closed Principle, OCP) 定义:软件实体应当对扩展开放,对修改关闭。这句话说...
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能...
开闭原则(OCP:Open-ClosedPrinciple)是指在进行面向对象设计(OOD:ObjectOrientedDesign)中,设计类或其他程序单位时,应该遵循:-对扩展开放(open)-对修改关闭(closed)的设计原则。开闭原则是判断面向对象...
中实用的面向对象设计 - 笔记 笔记: / 预订: 这是我在看书时做的一些笔记。 如果您想进行改进,请随时向我发送拉取请求。 第 1 章 - 面向对象设计 为什么要设计? 应用程序的变化是不可避免的。 由于对象之间的...
python开闭原则 开闭原则是面向对象设计中的一个重要原则,它指出一个软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着当需要添加新功能时,应该通过扩展现有代码来实现,而不是修改已有代码。...
每一个原则都蕴含一些面向对象设计的思想,可以从不同的角度提升一个软件结构的设计水平。 面向对象设计原则为支持可维护性替代而产生,这些原则蕴含在很多设计模式中,它们是从许多设计方案中总结出来的指导性原则...
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能...
面向对象设计的基本原则: OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。 DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程。 LoD...
AndroidDesignPattern针对《 Android原始码设计模式解析与实战》(第2版)这本书的的读书笔记面向对象6种设计原则1.单一职责原则一个类应该职能单一。2.开闭原则(开闭)一个类应该对扩展是开放的,对修改是关闭的。...
用到的面向对象设计的基本原则 OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。 DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程...
LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类(父类)可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类(父类),软件单位的功能不受到影响时,基类(父类)才能...
面向对象设计的5条规则 SRP单一责任原则 “一个班级应该只负一个责任。” 客户对象仅负责执行它。 DIP依赖关系逆转原理 “程序员应该依靠抽象的弧线,而不是具体的弧线。 依赖注入是遵循此原理的一种方法。” 示例...
java版五子棋源码 DesignPattern ...一个软件实体比如类、模块和函数应该对扩展开放,对修改关闭。对提供方扩展,对使用方闭关。用抽象构建框架,用实现扩展细节。 6.迪米特法则 即最少知道原则,一个类对自