在以前的一篇博客 Java Builder 模式,你搞懂了麼? 中,咱們提到了在 oop 編碼設計中 只要能拿到類的實例,即對象,就能命令對象作一系列事情了。在 java/android 程序中,每一個功能模塊都由 n 個 類所組成,而每一個類都封裝了各自的功能,咱們實例化每一個類的實例,分別命令他們去完成指定的功能,可是,程序設計中,類之間每每不是單獨去完成任務的,他們存在相互依賴的關係,就好比 A 類依賴 B 類,B 類又依賴 C 類,A 類 又同時依賴 C 類等等。這樣構成了一個錯綜複雜的關係網。先來個簡單代碼直觀的感覺~java
仍是以 製造 car 爲例子。CarCreateTechnology 製造汽車的技術封裝接口。android
public interface CarCreateTechnology { String createCar(); }
CarAutoCreate 製造汽車的技術封裝接口的實現類,具體邏輯由他實現。程序員
public class CarAutoCreate implements CarCreateTechnology{ @Override public String createCar() { return "自動生產的 car ~"; } }
CarFactory 汽車工廠類:segmentfault
public class CarFactory { private CarCreateTechnology mCreateTechnology; public CarFactory() { mCreateTechnology = new CarAutoCreate(); } public String createCar(){ return mCreateTechnology.createCar(); } }
最終 實例化 CarFactory 調用 createCar() 方法生產出 car
String car = new CarFactory().createCar();哈哈,這樣咱們的 car 就生產好啦,貌似很簡單嘛。網絡
嘟嘟~車開着正起勁的時候,有位客戶說了,不喜歡自動生產的汽車,想請個專業人員整一輛定製 car。這時候有人說這還不簡單,噼裏啪啦的敲敲敲,代碼修改以下:ide
Creater:定製 car 的製做者:函數
public class Creater { private String name;//汽車製造者名字 private String carType;//d定製 car 的類型 public Creater(String name, String carType) { this.name = name; this.carType = carType; } public String createCar(){ return this.carType; } }
CarAutoCreate 製造汽車的技術封裝接口的實現類:oop
public class CarAutoCreate implements CarCreateTechnology { private Creater mCreater;//定製 car 的製做者 public CarAutoCreate(Creater creater) { mCreater = creater; } @Override public String createCar() { return mCreater.createCar(); } }
CarFactory 汽車工廠類:ui
public class CarFactory { private CarCreateTechnology mCreateTechnology; public CarFactory(Creater creater) { mCreateTechnology = new CarAutoCreate(creater); } public String createCar(){ return mCreateTechnology.createCar(); } }
最後 調用 String car = new CarFactory(new Creater("張少林", "寶馬")).createCar();咱們的定製 car "寶馬" 就被製造出來啦。這樣修改起來貌似挺簡單的,可是存在如下一些問題this
分析問題
知道了問題所在,咱們來想辦法解決,畢竟不喜歡偷懶的程序員不是好程序員,咱們須要寫出一手優雅的代碼。
解決問題——依賴注入
java 中常見的依賴注入有三種:
咱們修改一下 CarFactory 的構造,將 CarCreateTechnology 做爲參數傳入,在構造中初始化全局 CarCreateTechnology 。
public class CarFactory { private CarCreateTechnology mCreateTechnology; public CarFactory(CarCreateTechnology createTechnology) { mCreateTechnology = createTechnology; } public String createCar(){ return mCreateTechnology.createCar(); } }
調用:String car = new CarFactory(new CarAutoCreate(new Creater("張少林", "寶馬"))).createCar();結果是同樣的,定製 car 同樣制形成功。可是不一樣的是:咱們沒有在 CarFactory 構造中直接構造所依賴的類(CarAutoCreate),而是經過傳入形參,由最終調用方去初始化依賴類,這樣就解決了以前的硬初始化問題,實現瞭解耦,提升了程序的可拓展性、可維護性。 眼毒的同窗確定發現了,咱們的 CarAutoCreate 就是經過構造方法依賴注入所需的依賴(Creater)。
CarFactory 添加 setxxx 注入全局變量。
public class CarFactory { private CarCreateTechnology mCreateTechnology; public void setCreateTechnology(CarCreateTechnology createTechnology) { mCreateTechnology = createTechnology; } public String createCar(){ return mCreateTechnology.createCar(); } }
調用:
CarFactory carFactory = new CarFactory(); carFactory.setCreateTechnology(new CarAutoCreate(new Creater("張少林","寶馬"))); String car = carFactory.createCar();
這種方法也是提供方法設置屬性進去,一樣也沒有直接在 CarFactory 中直接實例化依賴類,而是最終調用的時候初始化設置進去,一樣達到解耦目的。
接口注入跟 Setter 注入相似,只是用接口包裝了 Sertter 方法。這種方式易於管理。
public interface InjectTechnology { void injectCreate(CarCreateTechnology carCreateTechnology); }
CarFactory 實現接口。複寫方法。在方法中注入。、
public class CarFactory implements InjectTechnology{ private CarCreateTechnology mCreateTechnology; public String createCar(){ return mCreateTechnology.createCar(); } @Override public void injectCreate(CarCreateTechnology carCreateTechnology) { this.mCreateTechnology = carCreateTechnology; } }
"硬編碼" 和 "軟編碼",圖片來自網絡
最後,應該有的思考
咱們在 oop 編碼設計中,應該儘量的讓依賴類在最上層初始化,在細節中杜絕硬編碼。編寫解耦,有可拓展性、可維護性的代碼。
更多原創文章會在公衆號第一時間推送,歡迎掃碼關注 張少林同窗