oop - 如何组合使用对象(现实世界的例子)
问题描述
嘿,我对一个真实的例子有疑问。它与我的另外两个有关,但在这里没有真正回答问题:
https://softwareengineering.stackexchange.com/questions/423392/no-trivial-god-class-refactoring
和
假设我们有一个带有方法switchOn()
,的开关switchOff()
。开关包含在一些其他结构中,例如 a switch-bag
,我可以从中拉出开关。这可以看作是一个现成的系统。
现在我想介绍在一定时间后自动打开这些开关的可能性:Atime switch
time switch
现在的用途是"normal" switch
. normal switch
不必对time switch
.
所以,但现在客户可以normal switc
从 中提取 h switch-bag
,现在他还想获得time-switch
与这些相关的normal switch
,也许是为了配置一个新的时间。
这是我的问题,客户如何才能到达time-switch
?
有几种可能:
- 我将这个类重构
normal switch
为第三类,其中 捆绑normal-switch
了生命和生命。time switch
但为此,我打破了一些其他仍然使用 . 的客户端代码normal switch
,但现在从开关包中得到一个“组合器”-类/对象。 - 我不会改变
normal switch
课堂上的任何东西。客户如果想获得访问权限,则time switch
必须询问time switch
与其相关的地图。(我认为这种方法是经典的关系编程风格,如 sql 关系数据库,它不再是真正的面向对象风格) - 我扩展了
normal switch
:在这里我也有不同的选择:- 我将它更改为一个大外观,它将调用委托给
normal-switch
andtime switch
(它类似于我使用组合器的第一个解决方案,但这里的外观不会破坏一些现有的客户端代码) - 我扩展了
normal switch
让现有normal switch
代码保持不变的做法,并引入了一个组件支架。我将time switch
. 所以我有这些方法:switchOn();
switchOff();
getComponent("timeSwitch")
。但是这些方法感觉就像一个实体组件系统(https://medium.com/ingeniouslysimple/entities-components-and-systems-89c31464240d),但这仍然是面向对象的编程吗?
- 我将它更改为一个大外观,它将调用委托给
我认为最后一种解决方案是最好的,因为它最灵活。
但是你认为哪种方法是最好的,也许是我在这里没有提到的一些方法?
编辑:
您必须在这里知道的另一件事:time switch
是normal switch
. 其中之一。所以我当然想添加更多不同的东西 XYZ 开关/行为扩展normal switch
解决方案
更新:答案完全重写(所以第一条评论不再有意义)。
总结一下:
- SwitchBag 提供对开关列表/集合的访问。
- 开关有类似 on() 和 off() 的方法。
- 你想扩展至少一些开关的行为可以根据时间的流逝等自己做一些事情。
- 客户端(例如 UI)需要访问开关类。
你发表如下评论
现在他也想去与这些正常开关相关的时间开关
这表明您每个人都有一个,等等-这比需要的复杂得多。以下是一些需要考虑的选项 - 您的一些选项正朝着正确的方向前进。
选项 A:一种类型的开关
这假设解决方案设计和功能驱动程序不会促使您创建巨大且过于复杂的开关。例如,假设您的某些交换机需要在一段时间后执行某些操作,而其他交换机则不需要。这样的差异不一定足以构成单独的课程。
例如,您可以实现与时间相关的属性,例如Duration
,如果Duration
> 0 则应用时间逻辑并执行;< 0 表示不应用时间逻辑(正常开关行为)。
我在这里假设任何客户端都可以通过 SwitchBag 访问任何交换机。
这是我要开始的选项,因为它很简单并且仍然允许大量的功能范围。
选项 B:智能开关袋、哑开关
我不确定我是否喜欢这个选项的味道,因为它紧密耦合了 SwitchBag 和 Switch 类,但它可能很有用。
- 尽可能保持 switch 类的愚蠢。
- SwitchBag 了解开关,它控制对它们的访问(以及它们的属性/方法)。使用类结构和访问修饰符来控制它。
- 如果愿意,SwitchBag 可以根据时间决定对交换机进行处理。
在这种方法中,开关主要是属性,有点像 SwitchBags 个人数据库,只是它在运行时基于对象是流动的。
注意 - 您仍然可以在开关上设置事件。
选项 C:接口
创建一个基本开关。创建旨在应用于交换机类的接口,并根据需要扩展它们。例如:
interface ITimeBehaviour{
double InitialDuration
double TimeUntilChange
}
在运行时,您可以查看给定的开关实例是否实现了接口并做出相应的响应。但是,虽然您可以这样做,但根据我对您问题的理解,我不确定您为什么会这样做。
其他想法
您的评论表明您已经对继承和方法等 OO 概念进行了很多思考,但我没有看到您考虑过异步编程技术的证据 - 例如使用事件。如果您对此一无所知,请进行一些研究并加快速度,然后看看这是否为您的问题提供了一个优雅的解决方案。
设计模式——你熟悉设计模式的概念吗?如果你不是,一定要研究一下。网上有很多好的内容,描述了可能已经解决了你的问题的基本原理的模式。
推荐阅读
- xamarin - 错误 CS0534:[java 类] 未实现继承的抽象成员 'AsyncTask.DoInBackground(params Object[])'
- python - 嵌入python时Applescript输出读取问题
- html - Index.html 为空并显示 0bytes 但网页正在加载
- google-cloud-firestore - 如何允许身份验证部分下具有特定用户 UID 的用户写入 Firestore 并让其他用户读取特定文档的数据?
- python - 在 for 循环结束后不保留 Pandas DataFrames 中的更改
- pandas - 使用 panda 读取 .csv 并将单个列输出到单独的 .csv 文件中
- python - 如何在 selenium python 测试中设置等待条件
- json - 如何在laravel的特定字段下显示json响应?
- d - 如何 rawWrite 一个 Array!ubyte?
- node.js - 如何在 LINE 聊天机器人中使 profile.displayName 返回名称