合成复用法则(CRP)规定:在软件复用的时候应该优先使用组合或者聚合的方式实现关联,其次才考虑继承关系实现
如果要使用继承关系,则应该严格遵循里氏替换原则,合成复用和里氏替换原则都是开闭原则的具体实现
合成复用的实现方式有两种
- 继承:继承虽然简单方便,但同时也具备以下缺点
- 继承复用破坏了封装,父类的实现细节暴露给了子类
- 父子类的耦合度高,父类的任何改变都讲牵扯到子类
- 组合或聚合:可以将已有对象加入到新对象中,新对象可以调用已有功能,有以下优点
- 维持了封装,未暴露细节
- 耦合度低,对已有对象的操作都是通过接口调用
组合/聚合:
如下代码:A类中引用了B类,假设A对象消失,如果B对象没有其他引用,则B对象也会被GC,这就是组合。
而如果B对象被其他对象引用了,B对象则不会消失,这就是聚合。
static class A{B b;A(B b){this.b = b;}}static class B{A a;B(A a){this.a = a;}}
示例代码:
// 测试public static void main(String[] args) {ProductDao productDao = new ProductDao();productDao.setDbConnection(new PostgreSQLConnection());productDao.addProduct(); // addPostgresSQL conn}// 基类abstract static class DBConnection {public abstract String getConnection();}// mysql连接static class MySQLConnection extends DBConnection {@Overridepublic String getConnection() {return "MySQL conn";}}//PG连接static class PostgreSQLConnection extends DBConnection {@Overridepublic String getConnection() {return "PostgresSQL conn";}}// 组合static class ProductDao{private DBConnection dbConnection;public void setDbConnection(DBConnection dbConnection) {this.dbConnection = dbConnection;}public void addProduct() {String conn = dbConnection.getConnection();System.out.println("add" + conn);}}
