使用组合代替继承的理解

在设计模式原则中有“组合/聚合复用原则”,大部分网上说的概念比较笼统,不容易理解。因此将自己理解的内容记录下,供以后自己参考。

1. 组合与聚合的区别

  1. 聚合方式:A类的对象在创建时不会立即创建B类的对象,而是等待一个外界的对象传给它。
    聚合关系UML图,比较不强的关联,整体与个体的区别
  2. 组合方式:A类的构造方法里创建B类的对象,也就是说,当A类的一个对象产生时,B类的对象随之产生。
    组合关联关系,表示强关联,个体与部分的区别
    组合和聚合意义不同,但是在java中的引用形式是相同的。

2. 为什么要继承代替组合

在网上中一直是如下回答的:

①继承复用破坏了类的封装性。因为继承会将父类的实现细节暴露给子类,父类对子类是透明的,所以这种复用又称为“白箱”复用。
②子类与父类的耦合度高。父类的实现的任何改变都会导致子类的实现发生变化,这不利于类的扩展与维护。
③它限制了复用的灵活性。从父类继承而来的实现是静态的,在编译时已经定义,所以在运行时不可能发生变化。

假设一个系统需要使用一个数据库,则会如下编写:

class DBUtil{
	Connection getConnection(){
		return "mysql connection";
	}
}

如果使用了继承,其他的实体类的DBService如下:

class xxxDBService extends DBUtil {
	void insertXX(){
		super.getConnection()
		xx;
	}
}

(1)继承破坏了封装性
在DBUtil中getConnection方法是被封装了,但是xxDBservice继承了对应的类,这个时候xxDBService是可以重写对应的getConnection方法的,当然了一般而言的话也不会重写,但是如果重写了,并且没有保证里氏替换原则,这样的话就会有一定的风险。
(2)子类与父类的耦合度高
好的代码应该是需要高内聚,低耦合的,如果使用了继承的话,则其实是直接继承了细节,而不是抽象。在设计模式中有一个接口依赖原则,就是应该依赖接口,而不是依赖具体的实现类,子类和父类就绑定在一起了,这样如果父类修改了代码,则子类也会需要进行改动。
(3)限制了复用的灵活性
继承是继承了细节,这样编译后,是一个实实在在的代码了,无法在运行时灵活地改变getConnection中的内容了,如果系统需要在xxx环境下使用其他数据库,则继承是无法实现的,因为它不能在运行时根据改变其代码内容。可以使用组合加接口的方式,如下所示:

abstract class AbstractDButil{
Conection getConnection();
}


class MysqlDButil extends AbstractDButil {
Connection getConnection(){
		return "mysql connection";
	}
}

class OracleDButil extends AbstractDButil {
Connection getConnection(){
		return "oracle connection";
	}
}

class xxxDBService  {
	DButil dbutil;
	xxxDBService (DButil dbutil){
		this.dbutil = dbutil;
	}
	changeDButil(DButil dbutil){
		this.dbutil = dbutil;
	}
	void insertXX(){
		super.getConnection()
		xx;
	}
}

main(){

// 如果客户端选择了mysql作为存储
if(type="mysql"){
	xxxDBService.changeDButil(new OracleDButil());
	xxxDBService.insert();
}
}

二、总结

其实使用组合代替继承,能够加强类的扩展性,实现高内聚低耦合,这个原则也是体现了其他的原则;
如接口依赖原则:子类依赖了父类,而父类不是接口

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值