本文来了解一下什么是组合聚合复用原则。

定义

  • 尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的
  • 优点:可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少
  • 继承使白箱复用;组合聚合是黑箱复用。
  • 聚合:has-A;组合:contains-A;继承:is-A
  • 聚合:电脑和U盘,两者可以独立
  • 组合:国和家,没有国就没有家

例子

首先一个场景,是获取数据库连接,定义一个获取连接的类:

1
2
3
4
5
public class DBConnection {
public String getConnection(){
return "mysql数据库连接。。。";
}
}

下面我的产品需要获取这个数据库连接:

1
2
3
4
5
6
public class ProductDao extends DBConnection{
public void addProduct(){
String conn = super.getConnection();
System.out.println("获取"+conn);
}
}

那如果我可能要在多个数据之间切换呢?直接改不符合开闭原则,显然这个代码需要重构,将其用组合聚合来重构,定义一个抽象类:

1
2
3
public abstract class NewDBConnection {
abstract String getConnection();
}

Mysql数据库连接:

1
2
3
4
5
6
public class MysqlConnection extends NewDBConnection {
@Override
String getConnection() {
return "Mysql数据库连接...";
}
}

Oracle数据库连接:

1
2
3
4
5
6
public class OracleConnection extends NewDBConnection {
@Override
String getConnection() {
return "Oracle数据库连接...";
}
}

产品获取数据库连接,这里是用了组合模式:

1
2
3
4
5
6
7
8
9
10
11
12
public class NewProductDao extends DBConnection{
private NewDBConnection dbConnection;

public void setDbConnection(NewDBConnection dbConnection) {
this.dbConnection = dbConnection;
}

public void addProduct(){
String conn = dbConnection.getConnection();
System.out.println("获取"+conn);
}
}

那么,就可以在应用层进行切换了:

1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) {
NewProductDao productDao = new NewProductDao();
productDao.setDbConnection(new MysqlConnection());
productDao.addProduct();
}
}

image