我正在讨论正确的OO设计,以便从java类中使用另一个对象的功能(方法),而两个对象尽可能保持解耦。
例如,在我的类中的某个时刻,为了实现我的逻辑,我需要调用一个属于另一个对象的方法,比如一个帮助类。这个帮助器类不需要以任何方式与我的原始类相关,它只有一个特定的方法,可供我的类使用。
在实现逻辑之后,不需要帮助方法(或辅助对象)。
显然,我需要引用这个帮助器对象才能使用它的方法。但是为了强制封装,我不应该在我的原始类中声明一个实例变量来引用这个帮助器对象?这个推理是否正确?此外,帮助程序类不知道可能使用它的任何客户端类。
在这种情况下,局部变量会更合适吗?在方法中声明并实例化helper对象,它将利用它的功能?原始类中最好的位置在哪里声明并实例化这样的辅助对象?
我想知道是否有一个高级示例,或者是否在OO文章中对此进行了详细说明。我非常感谢任何以封装为中心的输入或提示。
答案 0 :(得分:2)
但是为了强制封装,我不应该在我的原始类中声明一个实例变量来引用这个帮助器对象?这种推理是否正确?
不,声明实例变量与破坏封装无关。
相关的考虑因素是:
基本选择是:
高级选择:
执行此操作的所有其他方法(例如,将对象添加到构造函数或方法参数)会向系统添加额外的依赖项,因此除非至少上述基本选项不合适,否则不应该这样做。
答案 1 :(得分:1)
正确的答案取决于辅助类(H)与您在其上使用的方法(M)和原始对象类(C)之间关系的性质。你提到了一些要点:
C
。H
。H.M()
仅由C
使用一次。H
与客户无关。H
的实例并且M()
是一个实例方法。有几种解决方案:
评估M
作为静态方法是否会更好。如果我见过静态方法,这对静态方法来说非常引人注目。你没有提到关于H维持状态的任何事情。
使用策略模式。如果H.M()
表示某种特定的做法,那么H
是C
模式中的策略对象}。如果还有其他类似H
类的M()
类,那么这些是您可以选择的不同策略。
答案 2 :(得分:0)
静态方法很难测试,或者说在另一种方法中调用的静态方法很难模拟。通过考虑测试,我发现很容易做好设计。如果该方法是非静态成员,则可以轻松地对调用该方法的代码进行单元测试,而无需测试该方法。你跟我在一起吗?假设一个方法m使用网络来做东西。如果该方法是静态的,那么每次测试使用方法m的代码时,它都会在网络上执行操作。如果网络内容失败,则测试失败,但不是您要测试的代码。你看?如果它不是静态的,您可以使用该方法模拟对象,并使其始终返回“OK”。
该说,我会将帮助器作为参数发送给方法,或者更确切地说是辅助接口。这样你的班级完全忘记了如何创建一个助手,甚至是什么类型。无知是幸福。该课程只会知道如何使用它,美丽的东西。 :)
答案 3 :(得分:0)
这是情景吗?这些是问题吗?
Class MyClass {
private SomeState myState;
public voic oneMethod() {
// Q1 : what type is **ahelper** ?
// Q2 : where do we declare it ?
// Q3 : where do we initialise it?
aHelper.doSomeWork();
// update your state depending upon the results
}
}
Q1。我认为你应该将aHelper声明为接口
HelperInterface aHelper;
然后我们没有加入任何特定的实现。
Q2。如果您只在一个地方使用它,请在该函数中声明它,否则作为成员变量。你不要通过这两种方式来增加耦合。
HelperInterface aHelper = ? what here?
aHelper.soSomeWork();
Q3。使用工厂在构造函数或惰性getter中初始化。
public MyClass(HelperInterface injectedHelper) {
aHelper = injectedHelper;
}
这可以使测试非常简单,您的测试可以注入Mocked Helper类。
或者你可以使用懒惰的intialiser。如果你的助手是你方法中的局部变量,这非常方便。工厂可以根据您的喜好再次注入或静电。
private getHelper() {
if (aHelper == null ){ make the helper, perhaps using a factory }
return aHelper
}
答案 4 :(得分:0)
我正在辩论正确的OO设计 使用另一个对象的功能 (方法)来自java类,而 两个对象保持分离 尽可能。
你在这方面付出了太多努力。解耦并不意味着根本没有连接。如果您要使用辅助对象一次,只需将其作为参数传递给使用它的块代码,或让您的类从工厂获取它的实例。
但在某些时候你必须有一个参考。显然,您不希望有一个成员实例引用它(潜在的内存泄漏)。所以这会调用某种工厂或实例管理器来获取对助手的引用。
但是不要过分夸大。目标是获得一个解决方案,而不是玩解耦游戏,让事情适合人为的冗余类层次结构。后者是OO概念的最坏用法。
答案 5 :(得分:-1)
为什么不选择static method或拥有singleton辅助对象?