博客
关于我
复合优于继承
阅读量: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/

你可能感兴趣的文章
NTP配置
查看>>
NUC1077 Humble Numbers【数学计算+打表】
查看>>
NuGet Gallery 开源项目快速入门指南
查看>>
NuGet(微软.NET开发平台的软件包管理工具)在VisualStudio中的安装的使用
查看>>
nuget.org 无法加载源 https://api.nuget.org/v3/index.json 的服务索引
查看>>
Nuget~管理自己的包包
查看>>
NuGet学习笔记001---了解使用NuGet给net快速获取引用
查看>>
nullnullHuge Pages
查看>>
NullPointerException Cannot invoke setSkipOutputConversion(boolean) because functionToInvoke is null
查看>>
null可以转换成任意非基本类型(int/short/long/float/boolean/byte/double/char以外)
查看>>
Numix Core 开源项目教程
查看>>
numpy
查看>>
NumPy 或 Pandas:将数组类型保持为整数,同时具有 NaN 值
查看>>
numpy 或 scipy 有哪些可能的计算可以返回 NaN?
查看>>
numpy 数组 dtype 在 Windows 10 64 位机器中默认为 int32
查看>>
numpy 数组与矩阵的乘法理解
查看>>
NumPy 数组拼接方法-ChatGPT4o作答
查看>>
numpy 用法
查看>>
Numpy 科学计算库详解
查看>>
Numpy.fft.fft和numpy.fft.fftfreq有什么不同
查看>>