面向对象的设计原则一 开放-关闭原则 - 森林狼 - JavaEye技术网站

来源:百度文库 编辑:神马文学网 时间:2024/05/13 20:06:44

动机

一个设计良好的应用程序应该充分考虑到开发和维护阶段需求的频繁变化,通常情况下,添加一个新的功能需要做出很多修改,我们应该使对已有代码的修改最小化,因为他们已经经过了测试。对现有代码做出修改将会以一种不可预料的方式影响它们的已有功能。

 

开放-关闭原则 (以下简称开闭原则)

开-闭原则:

一个软件实体应该对扩展开发,对修改关闭。

 

开闭原则是说我们应该努力设计不需要修改的模块。在扩展系统的行为时,我们只需要添加新的代码,而不需要修改已有的代码。一般可以通过添加新的子类和重写父类的方法来实现。

 

满足开闭原则的模块符合下面两个标准:

  • 对扩展开放 ------- 模块的行为可以被扩展从而满足新的需求。
  • 对修改关闭 ------- 不允许修改模块的源代码。(或者尽量使修改最小化)

这两个标准看似相互矛盾的,那么我们怎么实现他们呢?

怎样实现开闭原则

  • 抽象
  • 多态
  • 继承
  • 接口

要想使一个软件系统的所有模块都满足开闭原则是不太现实的,不过我们应该努力使大部分模块满足开闭原则。开闭原则是面向对象设计的核心,满足该原则可以达到最大限度的复用和可维护性。

 


实例

考虑下面某个类的方法:

 

Java代码
  1. public double totalPrice(Part[] parts) {   
  2. double total = 0.0;   
  3. for (int i=0; i
  4. total += parts[i].getPrice();   
  5. }   
  6. return total;   
  7. }  
public double totalPrice(Part[] parts) {double total = 0.0;for (int i=0; i

 

上面函数的功能是计算给定的零件数组中所有零件价格的总和,如果Part是一个基类或者接口,那我们就可以利用多态的特性,当有新的零件被添加进来时不需要修改该函数的代码。这样它就可以满足开闭原则。

 

但是如果我们的会计部门规定当计算主板和内存的价格时,需要添加一些额外的费用,请看下面的代码:

Java代码
  1. public double totalPrice(Part[] parts) {   
  2. double total = 0.0;   
  3. for (int i=0; i
  4. if (parts[i] instanceof Motherboard)   
  5. total += (1.45 * parts[i].getPrice());   
  6. else if (parts[i] instanceof Memory)   
  7. total += (1.27 * parts[i].getPrice());   
  8. else  
  9. total += parts[i].getPrice();   
  10. }   
  11. return total;   
  12. }  
public double totalPrice(Part[] parts) {double total = 0.0;for (int i=0; i

 

 

现在它还符合开闭原则吗?不!每次会计部门发布一个新的价格政策时,我们都需要修改totalPrice()方法!它对修改不是关闭的,显然,价格政策的改变意味着我们必须修改某处的代码,那么我们应该怎么做呢?为了使用我们第一个版本的totalPrice()方法,我们需要把Part的getPrice()方法的价格政策包含进来。

下面是Part和ConcretePrat类:

Java代码
  1. // Class Part is the superclass for all parts.   
  2. public class Part {   
  3. private double price;   
  4. public Part(double price) (this.price = price;}   
  5. public void setPrice(double price) {this.price = price;}   
  6. public double getPrice() {return price;}   
  7. }   
  8. // Class ConcretePart implements a part for sale.   
  9. // Pricing policy explicit here!   
  10. public class ConcretePart extends Part {   
  11. public double getPrice() {   
  12. // return (1.45 * price); //Premium   
  13. return (0.90 * price); //Labor Day Sale   
  14. }   
  15. }  
// 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); //Premiumreturn (0.90 * price); //Labor Day Sale}}

 

但是,现在如果价格政策改变,我们必须修改Part的子类,一个更好的方法是建立一个PricePolicy类,它可以为我们提供不同的价格政策:

Java代码
  1. /**  
  2. * Class PricePolicy implements a given price policy.  
  3. */  
  4. public class PricePolicy {   
  5. private double factor;   
  6. public PricePolicy (double factor) {   
  7. this.factor = factor;   
  8. }   
  9. public double getPrice(double price) {return price * factor;}   
  10. }  
/*** 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可以从数据库中获取。

 

总结

像许多其他原则一样,开闭原则只是面向对象设计的一个原则,实现一个灵活的设计需要额外的时间和努力,引入新的抽象层会增加代码的复杂性。因此,该原则适用于那些需求会经常发生变化的系统。有许多设计模式可以帮助我们扩展功能而不需要修改代码。例如,装饰模式等