博客
关于我
复合优于继承
阅读量:565 次
发布时间:2019-03-09

本文共 1705 字,大约阅读时间需要 5 分钟。

当通过子类继承父类并不是代码重用的最佳方式时,存在一个显著的问题:它打破了对象封装性。具体来说,当父类的实现细节发生变化时,如果子类直接继承自父类,子类也会随之受到影响。这意味着只要父类的方法被修改,子类都会相应改变,这使得子类对父类产生了强耦合。

以HashSet类为例,假设我们创建了一个TestHashSet类,直接继承自HashSet。为了统计插入的元素数量,我们在TestHashSet中重写了add()和addAll()方法,并引入了一个计数器。然而,我们发现当调用addAll()方法时,实际上内部会调用super的add()方法。这样一来,每次将元素添加到集合中,计数器会被增加两次,最终导致计数值翻倍。

这样的继承方式引入了“自用性”问题(intrinsic call),因为它使得子类方法内部直接调用了父类的方法。为了解决这一问题,我们可以采用复合和转发的方式,而不是直接继承。

复合和转发的方式意味着我们不再直接扩展现有的类,而是创建一个新的包装类,它包含现有的类实例,并通过转发方法公开新的功能。这样的设计不仅将信赖移到了执行环境中,使现有类的实现细节可以在不影响其他类的情况下进行修改,同时也提高了系统的健壮性。

以下是一个利用复合和转发设计原则改造后的类示例:

// 使用包装类代替直接继承public class InstrumentedSet implements Set
{ private final ForwardingSet
wrapped; private int addCount = 0; public InstrumentedSet(E[] elements) { wrapped = new ForwardingSet<>(elements); } // 转发方法调用wrapped对象的实现 @Override public boolean add(E e) { addCount++; return wrapped.add(e); } @Override public boolean addAll(Collection
c) { addCount += c.size(); return wrapped.addAll(c); } // 提供统计方法 public int getAddCount() { return addCount; }}// 转发类实现了Set接口,内部包含目标集合对象public class ForwardingSet
implements Set
{ private final Set
target; public ForwardingSet(E[] elements) { target = new HashSet
(Arrays.asList(elements)); } @Override public boolean add(E e) { return target.add(e); } // 转发其他方法调用 // ...}

通过这种方式,我们避免了直接继承HashSet,简化了包装类的设计,并确保了统计逻辑的准确性。

总结来说,继承并不是解决所有问题的最佳方式。只有当子类确实是父类的子类型时,才应该使用继承。为了避免因继承带来的问题,我们可以采用复合和转发的机制。这种方法不仅提高了系统的可维护性,也让我们的设计更灵活,同时最大限度地遵守了封装原则。

封装性是软件设计中的核心原则之一,它意味着每个类只应该处理自己的事务。如果我们通过继承直接耦合一个类的实现细节,就违反了封装性。而通过包装类,我们可以将复杂的逻辑隐藏起来,使其更加容易管理和扩展。

转载地址:http://ovepz.baihongyu.com/

你可能感兴趣的文章
No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
查看>>
No new migrations found. Your system is up-to-date.
查看>>
No qualifying bean of type XXX found for dependency XXX.
查看>>
No qualifying bean of type ‘com.netflix.discovery.AbstractDiscoveryClientOptionalArgs<?>‘ available
查看>>
No resource identifier found for attribute 'srcCompat' in package的解决办法
查看>>
no session found for current thread
查看>>
No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
查看>>
NO.23 ZenTaoPHP目录结构
查看>>
no1
查看>>
NO32 网络层次及OSI7层模型--TCP三次握手四次断开--子网划分
查看>>
NOAA(美国海洋和大气管理局)气象数据获取与POI点数据获取
查看>>
NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
查看>>
node exporter完整版
查看>>
Node JS: < 一> 初识Node JS
查看>>
Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime(72)
查看>>
Node 裁切图片的方法
查看>>
Node+Express连接mysql实现增删改查
查看>>
node, nvm, npm,pnpm,以前简单的前端环境为什么越来越复杂
查看>>
Node-RED中Button按钮组件和TextInput文字输入组件的使用
查看>>
Node-RED中Switch开关和Dropdown选择组件的使用
查看>>