当前位置:网站首页>优先使用对象组合,而不是类继承
优先使用对象组合,而不是类继承
2022-07-05 03:36:00 【跳动的bit】
《极限编程》(Extreme programming)的指导原则之一是“只要能用,就做最简单的”。一个似乎需要继承的设计常常能够戏剧性地使用组合来代替而大简化,从而使其更加灵活。因此,在考虑一个设计时,问问自己:“使用组合是不是更简单?这里真的需要继承吗?它能带来什么好处?”
继承和组合的比较:
面向对象系统中功能复用的两种最常用技术是类继承和对象组合(object composition)。正如我们已解释过的,类继承允许你根据其他类的实现来定义一个类的实现。这种通过生成子类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,父类的内部细节对子类可见。
对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。
继承和组合各有优缺点。类继承是在编译时刻静态定义的,且可直接使用,因为程序设计语言直接支持类继承。类继承可以较方便地改变被复用的实现。当一个子类重定义一些而不是全部操作时,它也能影响它所继承的操作,只要在这些操作中调用了被重定义的操作。
但是类继承也有一些不足之处。首先,因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现。更糟的是,父类通常至少定义了部分子类的具体表示。因为继承对子类揭示了其父类的实现细节,所以继承常被认为“破坏了封装性” 。子类中的实现与它的父类有如此紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,实现上的依赖性就会产生一些问题。如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。一个可用的解决方法就是只继承抽象类,因为抽象类通常提供较少的实现。
对象组合是通过获得对其他对象的引用而在运行时刻动态定义的。组合要求对象遵守彼此的接口约定,进而要求更仔细地定义接口,而这些接口并不妨碍你将一个对象和其他对象一起使用。这还会产生良好的结果:因为对象只能通过接口访问,所以我们并不破坏封装性;只要类型一致,运行时刻还可以用一个对象来替代另一个对象;更进一步,因为对象的实现是基于接口写的,所以实现上存在较少的依赖关系。
对象组合对系统设计还有另一个作用,即优先使用对象组合有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。另一方面,基于对象组合的设计会有更多的对象 (而有较少的类),且系统的行为将依赖于对象间的关系而不是被定义在某个类中。
这导出了我们的面向对象设计的第二个原则:优先使用对象组合,而不是类继承。
原文链接:https://www.cnblogs.com/nexiyi/archive/2013/06/16/3138568.html
边栏推荐
- English essential vocabulary 3400
- Analysis of glibc strlen implementation mode
- 【做题打卡】集成每日5题分享(第三期)
- 【无标题】
- Thread Basics
- The perfect car for successful people: BMW X7! Superior performance, excellent comfort and safety
- Binary heap implementation (priority queue implementation)
- 请问一下我的请求是条件更新,但在buffer中就被拦截了,这种情况我只能每次去flush缓存么?
- [punch in questions] integrated daily 5-question sharing (phase III)
- How to define a unified response object gracefully
猜你喜欢
[数组]566. 重塑矩阵-简单
51 independent key basic experiment
[untitled]
[groovy] string (string injection function | asBoolean | execute | minus)
postman和postman interceptor的安装
KVM virtualization
深度学习——LSTM基础
[software reverse - basic knowledge] analysis method, assembly instruction architecture
Leetcode42. connect rainwater
error Couldn‘t find a package.json file in “你的路径“
随机推荐
Clean up PHP session files
001 chip test
IronXL for .NET 2022.6
深度学习——LSTM基础
Cette ADB MySQL prend - elle en charge SQL Server?
【软件逆向-基础知识】分析方法、汇编指令体系结构
A brief introduction to the behavior tree of unity AI
请问一下我的请求是条件更新,但在buffer中就被拦截了,这种情况我只能每次去flush缓存么?
ICSI213/IECE213 Data Structures
@Transactional 注解导致跨库查询失效的问题
[punch in questions] integrated daily 5-question sharing (phase III)
speed or tempo in classical music
[groovy] loop control (number injection function implements loop | times function | upto function | downto function | step function | closure can be written outside as the final parameter)
About MySQL database connection exceptions
[2022 repair version] community scanning code into group activity code to drain the complete operation source code / connect the contract free payment interface / promote the normal binding of subordi
Excuse me, my request is a condition update, but it is blocked in the buffer. In this case, can I only flush the cache every time?
[software reverse - basic knowledge] analysis method, assembly instruction architecture
[Chongqing Guangdong education] 2777t green space planning reference questions of National Open University in autumn 2018
[groovy] string (string splicing | multi line string)
花了2晚,拿到了吴恩达@斯坦福大学的机器学习课程证书