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

你可能感兴趣的文章
Node响应中文时解决乱码问题
查看>>
node基础(二)_模块以及处理乱码问题
查看>>
node安装卸载linux,Linux运维知识之linux 卸载安装node npm
查看>>
node安装及配置之windows版
查看>>
Node实现小爬虫
查看>>
Node提示:error code Z_BUF_ERROR,error error -5,error zlib:unexpected end of file
查看>>
Node提示:npm does not support Node.js v12.16.3
查看>>
Node搭建静态资源服务器时后缀名与响应头映射关系的Json文件
查看>>
Node服务在断开SSH后停止运行解决方案(创建守护进程)
查看>>
node模块化
查看>>
node模块的本质
查看>>
node环境下使用import引入外部文件出错
查看>>
node环境:Error listen EADDRINUSE :::3000
查看>>
Node的Web应用框架Express的简介与搭建HelloWorld
查看>>
Node第一天
查看>>
node编译程序内存溢出
查看>>
Node读取并输出txt文件内容
查看>>
node防xss攻击插件
查看>>
noi 1996 登山
查看>>
noi 7827 质数的和与积
查看>>