开放关闭原则(Open-Closed Principle)

开放关闭原则(Open-Closed Principle)  

2011-07-27 19:29:37|  分类: 技术 |  标签:开放关闭原则  ocp  设计模式  |举报|字号 订阅

下载LOFTER客户端
开-闭原则: 一个软件实体应该对扩展开放,对修改关闭。

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

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

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

怎样实现开闭原则?

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

Example:

考虑下面某个类的方法:

 

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

 

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

 

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

Java代码   收藏代码
  1. public double totalPrice(Part[] parts) {  
  2.   double total = 0.0;  
  3.   for (int i=0; i<parts.length; 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. }  

 

现在它还符合开闭原则吗?不!每次会计部门发布一个新的价格政策时,我们都需要修改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. }  

 

但是,现在如果价格政策改变,我们必须修改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. }  

 

使用这种方法,我们可以在运行时动态的设置Part对象所引用的PricePoilcy对象,在实际的程序中,零件的价格和相关的PricePolicy可以从数据库中获取。


理解: 在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展。 
             其实这里所说的不被修改是指的重要的抽象层的模块不会被修改,这也就是使变化中的软 系统有一定的稳定性。当系统要扩展或者添加新的行为的时候只需要添加 另外实现的模块即可。由于新添加的模块继承于抽象层,所以实现了其不变性。 
              比如在策略模式中,OCP就得到了很好的体现,算法的不同实现其实就是对扩展的支持,而算法抽象类是对系统的不变性的支持,环境类包装了对于环境变化的控制与所采用算法的选择,当采用其他算法的时候只需要扩展算法类即可。  
               也就是说关键在于抽象,抽象出来的东西是不变的,具体的实 现继承于抽象,所以保证了对修改的Close,而抽象的实现方式有多种,可以随需添加,当然这也就是对扩展的Open。 另外要求的是技术包括:多态 Polymorphism,接口 Interface,继承 Inheritance.
 

注:另外在对可变性进行封装的时候也应该注意以下几点: 
          1.识别系统有可能变化的地方。 
          2.不要将一种可变形散布在多处代码,而应该封装起来。 
          3.不要将一种可变性与另外一种可变性混在一起。 
   

去观察及思考:变的与不变的块!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
3)A digital clock consists of a screen to display the time and a dial for setting in turn the year, month, day, hour and minute. Twisting the dial to the left reduces by one the value being changed but twisting it to the right increases it by one. Pushing the dial alters which value is being adjusted. At first, it is the year but after the dial is pushed once, it is the month, then after the dial is pushed again, it is the day and so on. Imagine the clock is represented by a class with attributes year, month, day etc. The following is what the code for a method rotateDialLeft() might look like. public void rotateDialLeft() { if (mode == YEAR_MODE) { year--; } else if (mode == MONTH_MODE) { month--; } else if (mode == DAY_MODE) { day--; } else if (mode == HOUR_MODE) { hour--; } else if (mode == MINUTE_MODE) { minute--; } } The code for rotateDialRight() is similar. Apply the Open-Closed Principle to explain why the above code is unsatisfactory from the design viewpoint, considering the possibility of future change to the code, giving an example of such a change. 5)Give the code required for the classes introduced in question 3), focusing on the code for a method selectState() which changes the value that is being adjusted from years to months. Make it clear in which classes the code is to be found. Assume the existence of other methods that are needed such as getMonthSetUpState(). 8)Suppose that in a multiplayer role-playing game, a class Client has a dependency to an interface Fighter with public methods attack(), defend() and escape(). The game designer now wishes for Client to use a class Wizard with three different but equivalent public methods castDestructionSpell(), shield() and portal(). Explain how it is possible to do this using an appropriate design pattern.
06-03

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值