设计模式的六大原则

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

  设计模式(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). 开:对扩展开放

      关:对修改关闭

 

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

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

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

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

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

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

 

posted @ 2017-05-09 18:07  小葱拌豆腐~  阅读(241)  评论(0编辑  收藏  举报