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

作者: 秦子帅 | 来源:发表于2017-09-25 09:32 被阅读182次

    简介:

    开闭原则(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 extends 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)-迪米特法则

    相关文章

      网友评论

        本文标题:六大设计原则详解(6)-开闭原则

        本文链接:https://www.haomeiwen.com/subject/yjsrextx.html