简介
- 定义:尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的。
- 聚合has-A和组合contains-A。
- 优点:可以使系统更加灵活,降低类与类之间的耦合度,一个雷的变化对其他类造成的影响相对较少。
继承复用虽然简单,但是存在很大的缺点:
(1)耦合度高,父类代码的修改会影响到子类,不利于代码的维护。
(2)破坏了类的封装性,因为继承会将父类的实现细节暴露给子类,所以又叫做 “白箱” 复用。
(3)限制了复用的灵活性,从父类继承来的实现是静态的,在运行期是无法改变的。
合成复用是将已有的对象作为新对象的成员对象来实现,新对象调用已有对象的功能,达到复用:
(1)不会破坏封装性,因为新对象只能调用已有对象暴露出来的方法,所以又叫做 “黑箱” 复用
(2)耦合度低,已有对象的变化对新对象的影响较小,可以在新对象的中,根据需要调用已有对象的一些操作。
(3)复用的灵活性高,可以在代码的运行中,动态选择相同类型的其他具体类。
实现参考
先看通过继承来复用的案例。
/**
* 数据库链接类,目前只有MySQL。
*/
public class DBConnection {
public String getConnection() {
return "MySQL数据库连接";
}
}
/**
* 通过继承来使用工具类的方法。后面如果改成Oracle了,需要修改代码。而且改了之后还会影响老功能。
*/
public class ProductDao extends DBConnection{
public void addProduct(){
String conn=super.getConnection();
System.out.println("使用"+conn+"增加产品");
}
}
/**
* 客户端使用
*/
public class CompositionAggregationTest {
public static void main(String[] args) {
ProductDao productDao = new ProductDao();
productDao.addProduct();
}
}
改成合成的方式复用。
/**
* 数据库链接类,改成抽象类,后面用不同的数据库实现类来继承他。
*/
public abstract class DBConnection {
public abstract String getConnection();
}
public class MySQLConnection extends DBConnection{
@Override
public String getConnection() {
return "MySQL数据库连接";
}
}
public class PostgreSQLConnection extends DBConnection{
@Override
public String getConnection() {
return "PostgreSQL数据库连接";
}
}
/**
* 通过成员变量合成复用。
*/
public class ProductDao {
private DBConnection dbConnection;
public void setDbConnection(DBConnection dbConnection) {
this.dbConnection = dbConnection;
}
public void addProduct() {
String conn = dbConnection.getConnection();
System.out.println("使用" + conn + "增加产品");
}
}
public class CompositionAggregationTest {
public static void main(String[] args) {
ProductDao productDao = new ProductDao();
productDao.setDbConnection(new PostgreSQLConnection());
productDao.addProduct();
}
}