接口和面向接口編程


 

在剛開始做開發的時候,我並不是很理解接口和面向接口編程在實際開發中的作用,比如:
  1)為什么需要 Service、DAO 的接口;
  2)為什么使用接口去引用依賴組件對象;
  3)為什么花費很大力氣去設計對象工廠、對象容器,然后又把對象注入到依賴組件;

這些問題真是花了很長時間才搞清楚!

 

我們都知道,web 開發是分層的:控制層、業務層、數據層、實體類等,以業務層和數據層的依賴關系為例,通常可以使用三種方式來編寫代碼。

第一種:不編寫接口,直接在業務層使用數據層的類來使用,簡單粗暴、好理解

  數據層類 xxDao = new 數據層類();

第二種:編寫接口和實現類,在業務層使用接口引用,但還是使用 new 關鍵字來實例化實現類對象,屬於脫褲子放屁類型。

  數據層接口 xxDao = new 數據層實現類();

第三種:編寫接口和實現類,在程序啟動的時候使用“工廠”來管理對象,在業務層使用接口引用,然后從“工廠”獲取需要的對象,或者使用框架注入,這里涉及到了多態和反射。

  數據層接口 xxDao = 工廠獲取/注入;

 

在不使用 Spring 或者自定義對象工廠的時候,前兩種方式都有可行,第二種方式可以為日后的架構設計升級提供一個接口規范,所以也是可以接受的。

在項目有了較大規模的時候,為了提高維護效率、實現組件之間的松耦合,我們會去設計“工廠”或者直接使用 Spring 來管理對象,這樣做的好處在於:

在整體修改了數據層實現類實現方式的時候(如:把 hibernate 改為 mybatis),不需要去修改業務層的任何代碼,只需要修改工廠配置文件即可實現組件的替換,因為任何一個符合“接口規范”的實現類對象都可以被注入到依賴該接口的業務類中去。

所以,我們有理由相信:反射、接口、多態是 Java 能夠成為動態編程語言的最主要原因。

 

在本文中,我們暫時不去看 Web 項目的組件解耦方案,之前有過一篇文章寫過自定義工廠的解耦方案,《多態和簡單對象工廠》,Spring 放到以后再去講解。

今天先用一個簡單的例子介紹一下反射、接口是如何提高程序擴展性、可維護性的。

 

我們的例子是這樣的:
  1)有 20 個業務需要進行監控,分屬三個類型:A、B、C,每個類型的業務監控邏輯大致相同
  2)以后可能會增加 D、E 業務類型
  3)每個類型的業務數量也會隨着項目的擴大而增加

我們需要設計一個方案,確保在業務類型、業務增加時可以快速的配置上線

 

第一種設計方案:

  1)編寫A、B、C三個類型的監控類代碼;
  2)在遍歷全部業務時,分支結構判斷業務類型,不同的類型創建不同的監控類對象,調用監控方法

  在我們的業務、業務類型增加時:需要增加相應的監控類;配置業務數據庫;修改分支結構。

  如果有很多個業務類型,10個、20個,顯然分支結構有些不美觀。

  所以還有一種使用接口和反射實現的方案。

 

第二種設計方案:

  1)編寫業務監控接口,有一個 doMinitor 方法;
  2)編寫 A、B、C 三個類型的監控類,實現業務監控接口;
  3)在遍歷全部業務時,通過業務類型獲取到對應的業務監控實現類類型,實例化對象;
  4)通過業務監控接口的引用調用業務監控實現類的 doMinitor 方法,對業務進行監控

  在我們的業務、業務類型增加時:需要增加相應的監控類;配置業務數據庫。

  所以,這個方案更加高大上。

 

我們簡單看一下編碼:

 

首先,Business 實體類用來保存業務信息

Business.java

 1 public class Business {
 2 
 3     private String businessName;
 4     private String monitorPolicy;
 5 
 6     public Business() {
 7         super();
 8     }
 9 
10     public Business(String businessName, String monitorPolicy) {
11         super();
12         this.businessName = businessName;
13         this.monitorPolicy = monitorPolicy;
14     }
15 
16     public String getBusinessName() {
17         return businessName;
18     }
19 
20     public void setBusinessName(String businessName) {
21         this.businessName = businessName;
22     }
23 
24     public String getMonitorPolicy() {
25         return monitorPolicy;
26     }
27 
28     public void setMonitorPolicy(String monitorPolicy) {
29         this.monitorPolicy = monitorPolicy;
30     }
31 }

 

接下來,編寫監控接口和三種類型業務的實現類

Monitor接口

1 public interface Monitor {
2 
3     void doMonitor(Business business);
4 
5 }

 

MonitorA類

1 public class MonitorA implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("監控業務類型A------" + business.getBusinessName());
6     }
7 }

 

MonitorB類

1 public class MonitorB implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("監控業務類型B------" + business.getBusinessName());
6     }
7 }

 

MonitorC類

1 public class MonitorC implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("監控業務類型C------" + business.getBusinessName());
6     }
7 }

 

最后,是 RunMonitor 入口類

 1 public class RunMonitor {
 2     
 3     private static List<Business> businessList = new ArrayList<Business>();
 4     
 5     static {
 6         businessList.add(new Business("業務01", "org.net5ijy.monitor.policy.MonitorA"));
 7         businessList.add(new Business("業務02", "org.net5ijy.monitor.policy.MonitorA"));
 8         businessList.add(new Business("業務03", "org.net5ijy.monitor.policy.MonitorA"));
 9         businessList.add(new Business("業務04", "org.net5ijy.monitor.policy.MonitorA"));
10         businessList.add(new Business("業務05", "org.net5ijy.monitor.policy.MonitorA"));
11         businessList.add(new Business("業務06", "org.net5ijy.monitor.policy.MonitorA"));
12         businessList.add(new Business("業務07", "org.net5ijy.monitor.policy.MonitorB"));
13         businessList.add(new Business("業務08", "org.net5ijy.monitor.policy.MonitorB"));
14         businessList.add(new Business("業務09", "org.net5ijy.monitor.policy.MonitorB"));
15         businessList.add(new Business("業務10", "org.net5ijy.monitor.policy.MonitorB"));
16         businessList.add(new Business("業務11", "org.net5ijy.monitor.policy.MonitorB"));
17         businessList.add(new Business("業務12", "org.net5ijy.monitor.policy.MonitorB"));
18         businessList.add(new Business("業務13", "org.net5ijy.monitor.policy.MonitorC"));
19         businessList.add(new Business("業務14", "org.net5ijy.monitor.policy.MonitorC"));
20         businessList.add(new Business("業務15", "org.net5ijy.monitor.policy.MonitorC"));
21         businessList.add(new Business("業務16", "org.net5ijy.monitor.policy.MonitorC"));
22         businessList.add(new Business("業務17", "org.net5ijy.monitor.policy.MonitorC"));
23         businessList.add(new Business("業務18", "org.net5ijy.monitor.policy.MonitorC"));
24         businessList.add(new Business("業務19", "org.net5ijy.monitor.policy.MonitorC"));
25         businessList.add(new Business("業務20", "org.net5ijy.monitor.policy.MonitorC"));33     }
34 
35     public static void main(String[] args) {
36 
37         for (Business business : businessList) {
38             String policyName = business.getMonitorPolicy();
39             try {
40                 Class<?> cls = Class.forName(policyName);
41 
42                 Monitor monitor = (Monitor) cls.newInstance();
43 
44                 monitor.doMonitor(business);
45 
46             } catch (ClassNotFoundException e) {
47                 e.printStackTrace();
48             } catch (InstantiationException e) {
49                 e.printStackTrace();
50             } catch (IllegalAccessException e) {
51                 e.printStackTrace();
52             }
53         }
54     }
55 }

 

項目結構如下:

 

 

 

 

 

過了一段時間,增加了業務類型 D、E,增加了五個業務,分屬 D、E,可以使用下面方式進行擴展:

 

MonitorD類

1 public class MonitorD implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("監控業務類型D------" + business.getBusinessName());
6     }
7 }

 

MonitorE類

1 public class MonitorE implements Monitor {
2 
3     @Override
4     public void doMonitor(Business business) {
5         System.out.println("監控業務類型E------" + business.getBusinessName());
6     }
7 }

 

項目結構如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM