面向接口編程,接口是什么,有什么作用?


    我從接觸java編程開始,書上、網上看到的都是面向接口編程,雖然一臉懵逼,但也沒有多想,這個和每個人的學習習慣有關系吧,我一直都是奉行着what how why的學習原則,管他是什么妥妥的就是干(copy),別人這么干我也這么干。公司里最常見的Spring 業務邏輯層應該是這樣的:

接口

public interface UserService {
    User findByUsername(String username);
}

實現類

@Service
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao dao;
@Override
public User findByUsername(String username) { return dao.findByUsername(username); } }

在很長一段時間里不明白為什么要這樣做,也沒有去深入研究,以至於再后來開發的時候直接去掉了實現類UserServiceImpl變成了這樣

@Service
@Transactional
public class UserService {
    @Autowired
    private UserDao dao;
    
    public User findByUsername(String username) {
        return dao.findByUsername(username);
    }
}

妥妥的沒毛病,程序少了接口,代碼都可以少敲點(幸福來的好突然)。在很長一段時間里整個公司都是這么干的,直到遇到了大一點項目(分布式部署,系統之間產生了交互),然后對接口有了新的認識,以下是自己對接口的一些理解。

 

很多其他行業在計算機面世之前就已經發展很久了,所以接口並不是計算機程序特有的,可以說接口無處不在。生活中很熟悉的插座

賣插座的廠商不一定會生產插頭,但是普通家電的三線插頭都是按照這樣的規范設計的,為了保證可以完美插入像這樣

當然香港買的腎7什么的,他的充電器插頭就不好插了,好尷尬WTF

像這樣的插頭就需要轉接頭了(設計模式中的適配器模式),廠商是按照不一樣的標准生成的,大陸有大陸的標准,香港有香港的標准。

接口是規范

插座是為了規范插頭生產廠商,USB接口是為了規范USB生產廠商,程序的接口是為了規范什么呢?為了規范廣大不同經驗不用閱歷的程序猿,為了實現類與類之間的松耦合。調用者只要按照接口規范傳入入參接口就會返回期望的出參(結果),具體是怎么實現的(內部結構,業務邏輯)調用者無需關心(像不像領導,只要結果不要過程,領導規定並調用接口,我們去實現)。

public interface SortService<T extends Comparable> {
    void sort(T[] array);
}

SortService的sort方法是給數組正序排序,在數組長度小的時候可能用簡單排序,冒泡排序就行了,大一點用歸並排序,在大一點用快速排序。對於調用者來說只關注排序的結果,不關注過程。

面向接口編程在協同開發的時候也是非常有作用的,假設兩個開發人員A和B一起開發一個商品購買的功能,商品購買的流程假設分為:庫存查詢和付款,

A負責開發查詢庫存,B負責開發付款;

A在查詢庫存返回還有庫存后需要調用付款流程;

B提供付款接口給A,A調用接口獲得付款結果;

B是怎么實現付款的,A不需要知道,哪天現有的付款邏輯不合適了,B重新開發了,也不會影響整個流程。

付款接口就是規范了B必須要按照接口的方法名,方法入參和出參類型來寫實現類。

接口是協議

http協議大家應該很熟悉(客戶端請求指定的地址可以當做是服務端提供的一個接口),請求報文格式如下:

服務器按照http約定的報文格式解析報文,客戶端按照http約定的報文格式提交報文獲得響應數據,至於服務器是怎么產生這些數據的客戶端不需要知道,客戶端只需請求服務器提供的鏈接地址就能獲取想要的數據,服務器和客戶端之間就實現了請求-響應的通信。       

最近開發的一個項目由多個子項目構成,項目與項目之間要相互調用對方的接口,項目里使用Hessian框架實現遠程接口調用,項目只需將接口和Dto打成jar包給客戶端,客戶端就能像使用本地的Bean一樣,實現調用了(Hessian真是簡單粗暴)。將接口暴露給客戶端,實現隱藏起來。

客戶端和服務端按照約定的協議進行數據交互,服務端按照約定的協議提供接口。

接口是標識

標識實現類可以做什么,不可以做什么,例如:java.io.Serializable接口,此接口沒有任何方法和字段,只是標識實現類是否可以序列化和反序列化。像這樣的空接口在實際開發中還有很多其他作用,比如標識實現類是否需要統計調用方法的執行時間(druid中的統計)、標識實現類是否需要記錄調用日志等等。

 

當然簡單的項目還是可以省去接口的,沒有必要搞的太復雜,少敲代碼可以實現相同的功能對於程序員來說就是幸福。但這種幸福往往是短暫的(重構和拓展就是噩夢)。


免責聲明!

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



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