首页 > 代码库 > 设计模式的六大原则

设计模式的六大原则

一、设计模式的概念及作用

  设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。

二、六大原则

 1.单一职责原则(Single Responsibility Principle,简称SRP)

  1) 概念:一个类只负责一项职责。

  2) 举例说明:假设有一个接口,如下:

 1   // 用户接口 2   public interface IUser{ 3       // 连接数据库方法 4       public Connection getConnection(); 5       // 查询用户 6       public User qryUser(User user); 7       // 增加用户 8       public int addUser(User user); 9   }

  当操作数据库的信息改变的时候,需要修改大量的代码,所以,可以将操作数据库的方法抽离出来,将上面的用户接口改为:

 1     // 数据库操作类 2     public class DBUtil{ 3         // 连接数据库方法 4         public static Connection getConnection(){....} 5     } 6  7     // 用户接口 8     public interface IUser{ 9         // 查询用户10         public User qryUser(User user);11         // 增加用户12         public int addUser(User user);13     }14 15     // 用户实现类16     public class UserImpl{17         Connection connection = null;18         // 查询用户19         public User qryUser(User user){20             connection = DBUtil.getConnection();21             ....22         }23         // 增加用户24         public int addUser(User user){25             connection = DBUtil.getConnection();26             ....27         }28     }

  即,用户接口中只操作用户的基本信息,不操作数据库。若要需要使用数据库操作,将数据库操作抽离出来,降低代码的耦合性。

  3) 优点:类的复杂度降低、可读性提高、可维护性提高、扩展性提高、降低了变更引起的风险。

 2.里氏替换原则(Liskov Substitution Principle,简称LSP)

  之所以叫里氏替换原则1988年,是因为该原则是由麻省理工学院的一位姓里的女士(Barbara Liskov)提出来的。

  1) 概念:所有引用父类的地方必须能 透明使用子类,反过来 不成立。

  2) 举例说明:

     喜欢动物 = 喜欢狗,因为动物中 包含狗,等式是成立的。

     喜欢狗 != 喜欢动物。 

        class Animal{}
        class Dog extends Animal{}

  3) 优点:增强程序的健壮性,即使增加了子类,原有的子类还可以继续运行。

 3.依赖倒置原则(Dependence Inversion Principle,简称DIP)

  1) 概念:依赖倒置原则的本质就是通过抽象(接口或抽象类)使个各类或模块的实现彼此独立,互不影响,实现模块间的松耦合。

  2)举例说明:假设有一个CD唱片,CD唱片的播放 需要 CD播放机,即:

 1     // CD 2     class CDRom{ 3         public void play(){ 4             System.out.println("play CDRom"); 5         } 6     } 7      8     // CD播放机 9     class Player{10         public void start(CDRom cd){11             System.out.println("CD playing ...");12             cd.play();13         }14     }15     16     // 测试方法17     public class Main{18         public static void main(Stirng[] args){19             Player player = new Player();20             CDRom cd = new CDRom();21             player.start(cd);22         }23     }

  随着科技的发达,DVD出现了,这时候就需要DVD播放机了,如下:

 1     // DVD 2     class DVDRom{ 3         public void play(){ 4             System.out.println("play DVDRom"); 5         } 6     } 7      8     // DVD播放器 9     class Player{10         public void start(CDRom cd){11             System.out.println("DVD playing ...");12             cd.play();13         }14     }

  又随着科技的发达,MP3、MP4等问世,这时候我们又需要定义更多的类,这样子会很繁琐,所以,可以定义一个上层接口,让下层的类去实现,将上面的代码 改为 如下:

 1     // 媒体接口 2     inteferce Media{        // cd,dvd,mp3,mp4.mp5... 3         public void play(); 4     } 5      6     // DVD,并实现媒体接口 7     class DVDRom impl Media{ 8         public void play(){ 9             System.out.println("play DVDRom");10         }11     }12     13     // CD,并实现媒体接口14     class CDRom impl Media{15         public void play(){16             System.out.println("play CDRom");17         }18     }19     20     // 通用播放机21     class Player{22         public void start(Media media){23             System.out.println("playing ...");24             media.play();25         }26     }27     28     // 测试方法29     public class Main{30         public static void main(Stirng[] args){31             Player player = new Player();32             media cd = new CDRom();33             34             media dvd = new DVDRom();35             player.start(dvd);36         }37     }

  3) 优点:在小型项目中很难体现出来。但在大中型项目中可以减少需求变化引起的工作量,使并行开发更友好。

 4.接口隔离原则(Interface Segregation Principle,简称ISP)

  1.概念:类间的依赖关系应该建立在最小的接口上。

     可以理解为:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

     一句话概括:一个接口中不要什么事情都去做,其实什么事情都做不好。

  2.举例说明:

 1     // 灯接口 2     interface light{ 3         // 开灯方法 4         on(); 5         // 关灯方法 6         off(); 7         // 维修方法 8         repare();  9         // 开电视方法10         turnOnTV();  11     }

  上面的灯接口中,既有灯的方法,又有工作人员的接口,又有电视的接口,这样 一个接口就会显得很臃肿,很庞大。

  运用接口隔离原则之后,将接口细化,分散为多个接口,可以预防外来变更的扩散。如下:

 1     // 灯接口 2     interface light{ 3         // 开灯方法 4         on(); 5         // 关灯方法 6         off(); 7     } 8      9     // 电视接口10     intefece tv{11         // 开电视接口12         on();13         // 关电视接口14         off();15     }16     17     // 工作人员18     intefece worker{19         // 维修20         repaire();21     }

  3.优点:通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

 5.迪米特法则(Law of Demeter,简称LoD)

  1.概念:类间解耦。

  2.问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。

  3.注意点:迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系。过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。

 6.开闭原则(Open Close Principle,简称OCP)

  1). 思想:尽量通过扩展软件实体来解决需求变化,而不是通过修改已有的代码来完成变化。

  2). 开:对扩展开放

      关:对修改关闭

 

  总结:单一职责原则告诉我们实现类要职责单一;

     里氏替换原则告诉我们不要破坏继承体系;

       依赖倒置原则告诉我们要面向接口编程;

       接口隔离原则告诉我们在设计接口的时候要精简单一;

           迪米特法则告诉我们要降低耦合;

       开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。  

 

设计模式的六大原则