设计原则 - 合成复用原则

概念

  • 合成复用原则(Composite Reuse Principle, CRP):尽量使用对象组合(contains-A)/聚合(has-A),而不是继承关系达到软件复用的目的。
  • 合成复用原则就是在一个新的对象里通过关联关系(包括组合关系和聚合关系)来使用一些已有的对象,使之成为新对象的一部分;新对象通过委派调用已有对象的方法达到复用功能的目的。
  • 优点:可以使系统更加灵活,降低类与类之间的耦合度,一个类的变化对其他类造成的影响相对较少。
  • 合成复用是达到开闭原则的一种实现方式。

编码

实例

  • 数据库连接,采用mysql作为数据库
  • DBConnection.java
/**
 * @Description DB连接
 * @date Dec 19, 2021
 * @version 1.0
 */
public class DBConnection {

	/**
     * 获取DB连接
     * @return
     */
    public String getConnection() {
        return "Mysql数据库连接";
    }

}
  • ProductDao.java
/**
 * @Description 产品DAO
 * @date Dec 19, 2021
 * @version 1.0
 */
public class ProductDao extends DBConnection {

    /**
     * 添加产品
     */
    public void addProduct() {
        String conn = super.getConnection();
        System.out.println("使用" + conn + "增加产品");
    }

}
  • Test.java
/**
 * @Description 测试类
 * @date Dec 19, 2021
 * @version 1.0
 */
public class Test {

    public static void main(String[] args) {
        ProductDao productDao = new ProductDao();
        productDao.addProduct();
    }

}
  • 输出:
使用Mysql数据库连接增加产品
  • 类图如下:

在这里插入图片描述

  • 由于在初始设计方案中DBConnectionProductDao之间是继承关系,因此在更换数据库连接方式时需要修改DBConnectionProductDao的源代码,这将违反开闭原则

合成复用原则

  • 实现数据库连接的扩展性,使用关联复用来取代继承复用

  • DBConnection.java

/**
 * @Description DB连接
 * @date Dec 19, 2021
 * @version 1.0
 */
public abstract class DBConnection {

    /**
     * 获取DB链接
     * @return
     */
    public abstract String getConnection();

}
  • MysqlConnection.java
/**
 * @Description Mysql连接
 * @date Dec 20, 2021
 * @version 1.0
 */
public class MysqlConnection extends DBConnection {
    @Override
    public String getConnection() {
        return "Mysql数据库连接";
    }
}
  • OracleConnection.java
/**
 * @Description Oracle连接
 * @date Dec 20, 2021
 * @version 1.0
 */
public class OracleConnection extends DBConnection {
    @Override
    public String getConnection() {
        return "Oracle数据库连接";
    }
}
  • ProductDao.java
/**
 * @Description 产品DAO
 * @date Dec 19, 2021
 * @version 1.0
 */
 public class ProductDao {

    private DBConnection dbConnection;

    /**
     * setter注入
     * @param dbConnection
     */
    public void setDbConnection(DBConnection dbConnection) {
        this.dbConnection = dbConnection;
    }

    /**
     * 添加产品
     */
    public void addProduct() {
        String conn = dbConnection.getConnection();
        System.out.println("使用" + conn + "增加产品");
    }

}
  • Test.java
/**
 * @Description 合成复用原则测试类
 * @author Coisini
 * @date Dec 19, 2021
 * @version 1.0
 */
public class Test {

    public static void main(String[] args) {
        ProductDao productDao = new ProductDao();
        productDao.setDbConnection(new MysqlConnection());
        productDao.addProduct();

        productDao.setDbConnection(new OracleConnection());
        productDao.addProduct();
    }

}
  • 输出:
使用Mysql数据库连接增加产品
使用Oracle数据库连接增加产品
  • 类图变化如下:

在这里插入图片描述

  • ProductDaoDBConnection的关系由继承关系变为关联关系,采用依赖注入的方式将DBConnection对象注入到ProductDao中,DBConnection的扩展通过其子类实现,根据里氏替换原则,DBConnection的子类可以覆盖DBConnection对象,只需在ProductDao中注入DBConnection的子类对象即可使用子类所扩展的方法,通过这种方式,原有代码无需修改,还可以灵活的增加新的数据库连接方式。

源码


- End -
- 个人学习笔记 -
- 仅供参考 -

posted @ 2021-12-20 10:25  Maggieq8324  阅读(428)  评论(0编辑  收藏  举报