合成复用法则(CRP)规定:在软件复用的时候应该优先使用组合或者聚合的方式实现关联,其次才考虑继承关系实现

    如果要使用继承关系,则应该严格遵循里氏替换原则,合成复用和里氏替换原则都是开闭原则的具体实现

    合成复用的实现方式有两种

    1. 继承:继承虽然简单方便,但同时也具备以下缺点
      • 继承复用破坏了封装,父类的实现细节暴露给了子类
      • 父子类的耦合度高,父类的任何改变都讲牵扯到子类
    2. 组合或聚合:可以将已有对象加入到新对象中,新对象可以调用已有功能,有以下优点
      • 维持了封装,未暴露细节
      • 耦合度低,对已有对象的操作都是通过接口调用

    组合/聚合:
    如下代码:A类中引用了B类,假设A对象消失,如果B对象没有其他引用,则B对象也会被GC,这就是组合。
    而如果B对象被其他对象引用了,B对象则不会消失,这就是聚合。

    1. static class A{
    2. B b;
    3. A(B b){
    4. this.b = b;
    5. }
    6. }
    7. static class B{
    8. A a;
    9. B(A a){
    10. this.a = a;
    11. }
    12. }

    示例代码:

    1. // 测试
    2. public static void main(String[] args) {
    3. ProductDao productDao = new ProductDao();
    4. productDao.setDbConnection(new PostgreSQLConnection());
    5. productDao.addProduct(); // addPostgresSQL conn
    6. }
    7. // 基类
    8. abstract static class DBConnection {
    9. public abstract String getConnection();
    10. }
    11. // mysql连接
    12. static class MySQLConnection extends DBConnection {
    13. @Override
    14. public String getConnection() {
    15. return "MySQL conn";
    16. }
    17. }
    18. //PG连接
    19. static class PostgreSQLConnection extends DBConnection {
    20. @Override
    21. public String getConnection() {
    22. return "PostgresSQL conn";
    23. }
    24. }
    25. // 组合
    26. static class ProductDao{
    27. private DBConnection dbConnection;
    28. public void setDbConnection(DBConnection dbConnection) {
    29. this.dbConnection = dbConnection;
    30. }
    31. public void addProduct() {
    32. String conn = dbConnection.getConnection();
    33. System.out.println("add" + conn);
    34. }
    35. }