面向介面程式設計,介面是什麼,有什麼作用?
我從接觸java程式設計開始,書上、網上看到的都是面向介面程式設計,雖然一臉懵逼,但也沒有多想,這個和每個人的學習習慣有關係吧,我一直都是奉行著what how why的學習原則,管他是什麼妥妥的就是幹(copy),別人這麼幹我也這麼幹。公司裡最常見的Spring 業務邏輯層應該是這樣的:
介面
public interface UserService { User findByUsername(String username); }
實現類
@Service @Transactional public class UserServiceImpl implements UserService { @Autowiredprivate UserDao dao;
@Override
public User findByUsername(String username) { return dao.findByUsername(username); } }
在很長一段時間裡不明白為什麼要這樣做,也沒有去深入研究,以至於再後來開發的時候直接去掉了實現類UserServiceImpl變成了這樣
@Service @Transactional public class UserService { @Autowired private UserDao dao; publicUser 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中的統計)、標識實現類是否需要記錄呼叫日誌等等。
當然簡單的專案還是可以省去介面的,沒有必要搞的太複雜,少敲程式碼可以實現相同的功能對於程式設計師來說就是幸福。但這種幸福往往是短暫的(重構和拓展就是噩夢)。