在以前的一篇博客 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 编码设计中,应该尽量的让依赖类在最上层初始化,在细节中杜绝硬编码。编写解耦,有可拓展性、可维护性的代码。
更多原创文章会在公众号第一时间推送,欢迎扫码关注 张少林同窗