26
2017
09

六大设计原则详解(6)-开闭原则

简介:

开闭原则(OCP)是面向对象设计中“可复用设计”的基石,是面向对象设计中最重要的原则之一,其它很多的设计原则都是实现开闭原则的一种手段。对于扩展是开放的,对于修改是关闭的,这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。也就是说,我们可以改变模块的功能。对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。模块的二进制可执行版本,无论是可链接的库、DLL或者.EXE文件,都无需改动。

软件实体包括:
项目或软件产品中按照一定的逻辑规则划分的模块
抽象和类
方法


下面通过实例来详细了解一下:
现在有个书店售书的场景,首先定义一个IBook类,里面有两个属性:名称、价格。

public interface IBook{
public String getName();
public int getPrice();
}

定义小说类NovelBook-实现类

public class NovelBook implements IBook{ 
  private String name;
   private int price;   
  public NovelBook(String name,int price){  
   this.name = name;     t
his.price = price;   
    }
   public String getName(){ 
    return this.name; 
  }    
 public int getPrice(){   
  return this.price;
   } }

下面是Client类

public class Client{ 
  public static void main(Strings[] args){  
   NovelBook novel = new NovelBook("笑傲江湖",100,"金庸"); 
    System.out.println("书籍名字:"+novel.getName()+"书籍价格:"+novel.getPrice()); 
  }}

下面有个需求需要更改,”如果书籍的价格在50以上,就打九折出售” 对于这样的需求变化,下面有三种方法可以解决:

1.修改接口
在IBook接口中新增一个getDisPrice(),专门用来打折处理,实现类重新实现该接口。这样的修改NoverlBook和Client都要修改,而且接口本身就要求稳定,不能随意修改,所以这个方法不可取。

2.修改实现类
修改NoverlBook类中的方法,直接在房里加入打折的逻辑,但是有个问题,别人很难知道此书是否被打折了,而且写在这里容易造成价格对不上等错误,所以此方法不可取。

3.扩展实现变化
新增一个子类DisNoverlBook类,并覆写getPrice()方法,产生新的对象,修改的代码很少,影响也小。下面是DisNoverlBook类具体代码:

public class DisNovelBook implements NovelBook{
    public DisNovelBook (String name,int price){  
       super(name,price,author);       
   }       
     //覆写价格方法,当价格大于50,就打9析 
     public int getPrice(){   if(this.price > 50){  
     return this.price * 0.9;     
      }else{        
    return this.price ;    
            }     
         }       }

在Client中只要修改一下实现类对象就可以了:

public class Client{
   public static void main(Strings[] args){  
     DisNovelBook disnovel = new DisNovelBook ("笑傲江湖",100,"金庸");   
       System.out.println("书籍名字:"+disnovel .getName()+"书籍价格:"+disnovel .getPrice());     
        } }

开闭原则对扩展开放,对修改关闭,并不意味着不做任何的修改,底层模块的变更,必然有高层模块进行耦合。


二.如何使用开闭原则
抽象约束

通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法;
参数类型、引用对象尽量使用接口或者抽象类,而不是实现类;
抽象层尽量保持稳定,一旦确定即不允许修改。
元数据(metadata)控制模块行为

元数据就是用来描述环境和数据的数据,通俗地说就是配置参数,参数可以从文件中获得,也可以从数据库中获得。
Spring容器就是一个典型的元数据控制模块行为的例子,其中达到极致的就是控制反转(Inversion of Control)
制定项目章程

在一个团队中,建立项目章程是非常重要的,因为章程中指定了所有人员都必须遵守的约定,对项目来说,约定优于配置。
封装变化


三.为什么使用开闭原则

开闭原则非常有名,只要是面向对象编程,在开发时都会强调开闭原则
开闭原则是最基础的设计原则
开闭原则可以提高复用性
开闭原则可以提高维护性
面向对象开发的要求


至此六大设计原则都写完了,主要参考了<大话设计模式><设计模式之禅>,其他五个原则链接如下:
推荐阅读

六大设计原则详解(1)-单一职责原则

六大设计原则详解(2)-里氏替换原则

六大设计原则详解(3)-依赖倒置原则

六大设计原则详解(4)-接口隔离原则

六大设计原则详解(5)-迪米特法则

上一篇:2017年腾讯移动客户端面试总结-失败经验 下一篇:基于ViewDragHelper实现侧滑