依赖倒置引出
依赖倒置
定义:高层模块不应该依赖低层模块,二者都应该依赖抽象;抽象不应该依赖细节,细节应该依赖抽象。面向接口编程而不是面向实现编程。
通过抽象使用抽象类、接口让各个类or模块之间独立不影响,实现模块之间的松耦合,降低模块之间的耦合性。
注意:每个类都尽量实现接口or继承抽象类;尽量避免从具体的类派生;尽量不要覆盖基类方法。
优点:减少类之间耦合性;提高系统稳定性、可维护性、代码可读性。
依赖倒置案例
public class Customer {
public void buyTV() {
System.out.println("买电视机");
}
public void buyPhone() {
System.out.println("买手机");
}
}
//试问?如果需要买其他商品呢,就要在这个具体Customer类中去加方法,可维护性低。
依赖倒置——接口注入
//顾客类
public class Customer {
public void buy(IGood iGood) {
iGood.buy();
}
}
//商品的接口
public interface IGood{
void buy();//抽象的buy方法
}
//电视机商品
public class TVGood implements IGood {
@Override
public void buy() {
System.out.println("买电视机");
}
}
//手机商品
public class PhoneGood implements IGood {
@Override
public void buy() {
System.out.println("买手机");
}
}
public class Main {
public static void main(String[] args) {
Customer customer = new Customer();
customer.buy(new TVGood());
}
}
依赖倒置——构造器注入
public class Customer {
private IGood iGood;
public Customer(IGood iGood) {
this.iGood = iGood;
}
public void buy() {
this.iGood.buy();
}
}
public class Main {
public static void main(String[] args) {
Customer customer = new Customer(new TVGood());
customer.buy();
}
}
依赖倒置——Setter注入(推荐)
public class Customer {
private IGood iGood;
public void setiGood(IGood iGood) {
this.iGood = iGood;
}
public void buy() {
this.iGood.buy();
}
}
合成复用原则引出
合成复用原则
定义:想要达到软件复用的目的,尽量使用对象组合/聚合,而不是继承关系;
组合:A类中包含了B类的引用,当A类对象销毁时,B类引用所指向的对象也一同消失,没有任何一个引用指向他,该引用成为了垃圾对象,被回收;
聚合:加入A类销毁后,B类对象还有在其它位置被引用,B类对象不会被销毁,
电脑与鼠标是聚合关系,电脑毁了,鼠标可以独立存在,还可以接在其它电脑上;
合成复用优点:系统更加灵活,降低类之间耦合度,一个类的变化对其他类造成的影响相对较少;
合成复用缺点:通过组合/聚合方式建造的系统,有较多的对象需要管理;继承复用优点:易扩展;
继承复用缺点:白箱复用,继承将父类的实现细节暴露给了子类;
继承复用案例
/**
* 数据连接
*/
public class DBConnection {
public String getConnection() {
return "数据连接";
}
}
public class ProDao extends DBConnection {
/**
* 增加产品
*/
public void addProduct() {
// 父类super获取连接
String conn = super.getConnection();
System.out.println("使用 " + conn + " 增加产品");
}
}
public class Main {
public static void main(String[] args) {
ProductDao proDao = new ProDao();
productDao.addProduct();
}
}
合成复用案例
/**
* 抽象类
*/
public abstract class DBConnection {
public abstract String getConnection();
}
/**
* MySQL连接
*/
public class MySqlConnection extends DBConnection {
@Override
public String getConnection() {
return "MySQL数据库连接";
}
}
/**
* Oracle连接
*/
public class OracleConnection extends DBConnection {
@Override
public String getConnection() {
return "Oracle数据库连接";
}
}
//----------------------------------------------------------------------
/**
* 增加数据
*/
public class ProDao {
/**
* 组合方式注入数据库连接
*/
private DBConnection connection;
public ProductDao(DBConnection connection) {
this.connection = connection;
}
/**
* 新增
*/
public void addProduct() {
// 获取连接
String conn = connection.getConnection();
System.out.println("使用 " + conn + " 增加产品");
}
}
public class Main {
public static void main(String[] args) {
ProductDao proDao = new ProDao(new MysqlConnection());
productDao.addProduct();
}
}