- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有两个类:
class A {
final B b;
A(final B b) {
this.b = b;
}
void doIt() {
b.doSomething();
}
void doSomething() {
// TODO Auto-generated method stub
}
}
和
class B {
final A a;
B(final A a) {
this.a = a;
}
void doIt() {
a.doSomething();
}
void doSomething() {
// TODO Auto-generated method stub
}
}
无法实例化它们中的任何一个。
我可以使用 setter,例如:
class B {
A a;
B() {
}
void setA(final A a) {
this.a = a;
}
void doIt() {
a.doSomething();
}
void doSomething() {
// TODO Auto-generated method stub
}
}
但在这里我需要检查 a
正在null
在 doIt()
并处理此案。这不是世界末日,但也许
有更聪明的方法吗?
或者这可能甚至是一般的反模式,并且首先是架构出了问题?
问题的根源:
我有一个从中加载实体的数据库。我在加载后缓存它们,并使用此缓存在类型之间建立双向关系。这是必要的,因为当我加载 A
的多个实例时,他们应该(在这种情况下)具有 B
的所有相同实例.因此 B 需要在之前实例化并重新使用。但是B
也与所有这些有关a
s,因此是循环依赖。
简而言之,循环依赖是由数据库中的双向关系引起的。我曾经尽可能避免使用它们,但除了此处描述的问题之外,双向关系不存在“现实世界”问题,事实上这是很自然的事情。
所以也许问题应该是如何将双向关系从关系数据库正确映射到 oop 世界?
更具体的例子:
为了建立双向关系,我从缓存中加载实例,这样当实体 ID 相同时我就有相同的实例:
interface Cache<T>
interface CacheA extends Cache<A>
interface CacheB extends Cache<B>
class CacheManager {
final CacheA cacheA;
final CacheB cacheB;
CacheManager(final DatabaseAccess databaseAccess) {
cachA = new CacheA();
cachB = new CacheB();
cacheA.setEntityLoader(id -> new SimpleAttachedA(id, databaseAccess, cacheB));
cacheB.setEntityLoader(id -> new SimpleAttachedB(id, databaseAccess, cacheA));
}
}
A
的实例如果与 B
的关系将访问此缓存被访问。反之亦然。
我知道最好是 CacheA
和 CacheB
将是同一个对象,从那时起我可以创建缓存并将其传递给 A
的所有实例和 B
.
CacheA
和 CacheB
曾经是一样的,即Cache
.我选择将它们分开,这样我就可以使用通用类并删除大量重复代码。
CacheManager
无法实现 CacheA
和 CacheB
, 如果它们都扩展相同的通用接口(interface) Cache<T>
但不同类型的 T
.
因此CacheManager
使用组合而不是继承。所以我最终得到两个缓存,需要互相访问才能实现A
的双向关系和 B
.
最佳答案
循环依赖通常是糟糕设计的标志。在某些情况下,您无法避免循环依赖,但您应该始终考虑其他解决方案。当您有循环依赖时,您很可能会更改其中一个类,并且还必须更改另一个类。当您的循环包含两个以上的类时,这可能需要大量工作。还出现了您提到的问题,“我需要另一个类来实例化其中一个”。
由于您的类(class)似乎是虚拟类(class),因此我无法给出真正好的建议,但仍然有一些一般性的要点。
类应该具有高内聚和低耦合。意思是,类应该尽可能少地依赖另一个类(低耦合),而每个类都应该做一个功能,并且所有的功能(高内聚)。
当你有两个相互依赖的类时,这通常是低内聚的标志,因为一部分功能在类 A
中,另一部分在类 B
。在这种情况下,您应该考虑将两个类合并为一个类。
另一方面,当您尝试为该合并类找到一个类名并想出类似 ThisAndThatDoer
的东西时,您应该将它们分成两个类 ThisDoer
和ThatDoer
,因为这是低内聚的标志。当您的原始类再次相互依赖时,您可以创建一个新类 Executor
来连接这两个类。但这很快就会成为一个神类,这也是一种反模式。所以你应该小心这一点。
总而言之,我建议考虑您的类设计并找到一种方法至少在一个方向上消除依赖性。我希望这有助于解决您的问题。
关于java - 类型 A 和 B 之间的循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45529749/
我有两种结构,Header 和Session,它们都符合协议(protocol)TimelineItem。 我有一个 Array 由 TimelineItem 组成,如下所示: [Header1, S
这个问题在这里已经有了答案: Multiple assignment and evaluation order in Python (11 个答案) 关闭 6 年前。 我刚接触python所以想问你
我试图找到一种方法来在 R 中获取 A、A、A、A、B、B、B、B、B 的所有可能的唯一排列的列表。 组合最初被认为是获得解决方案的方法,因此组合的答案。 最佳答案 我认为这就是你所追求的。 @bil
我怎样才能将两个给定的向量混合成一个新的向量,它以交替的顺序保存它们的值。 (f [a a] [b b]) ; > [a b a b] 这是我想到的: (flatten (map vector [:a
这是我的第一个问题,我开始学习Python。之间有区别吗: a, b = b, a + b 和 a = b b = a + b 当您在下面的示例中编写它时,它会显示不同的结果。 def fib(n):
这个问题在这里已经有了答案: Why is there an injected class name? (1 个回答) 12 个月前关闭。 我不知道如何解释: namespace A { struct
我尝试了一些代码来交换 Java 中的两个整数,而不使用第三个变量,使用 XOR。 这是我尝试过的两个交换函数: package lang.numeric; public class SwapVars
假设类 B 扩展类 A,并且我想为 B 声明一个变量。什么更有效?为什么? B b或 A b . 最佳答案 您混淆了两个不同的概念。 class B extends A { } 意味着B 是 A .
我不确定这个问题的标题是什么,这也可能是一个重复的问题。所以请相应地指导。 我是 python 编程的新手。我有这个简单的代码来生成斐波那契数列。 1: def fibo(n): 2: a =
我在谷歌上搜索了有关 dynamic_cast 的内容,我发现显式地将基类对象转换为派生类指针可能是不安全的。但是当我运行一些示例代码来检查它时,我没有收到任何错误。请在下面找到我的代码: class
这个问题在这里已经有了答案: What is this weird colon-member (" : ") syntax in the constructor? (14 个答案) 关闭 8 年前。
在不重现产生非整数值的表达式的情况下实现以下目标的惯用方法是什么(在我的真实情况下,该值是在我不想重现的冗长查询之后计算为百分比的): SELECT * FROM SomeTable WHERE 1/
在析构中,这两个代码的结果确实不同。我不确定为什么。 提示说 const [b,a] = [a,b] 将导致 a,b 的值为 undefined (从左到右的简单分配规则)。我不明白为什么会这样。 l
C++ Templates - The Complete Guide, 2nd Edition介绍max模板: template T max (T a, T b) { // if b < a th
我最近开始学习代码(Java),并根据第 15.17.3 节在 Oracle 网站上查找了模运算符。以下链接: http://docs.oracle.com/javase/specs/jls/se8/
无法理解以下行为。 d1 := &data{1}; 的区别d1 和 d2 := 数据{1}; &d1。两者都是指针,对吧?但他们的行为不同。这里发生了什么 package main import "f
这个问题在这里已经有了答案: How to make loop infinite with "x = y && x != y"? (4 个回答) How can i define variables
在我的程序中,当我调试我的代码时,它似乎在我生成的代码中的某处 X1=['[a,a,a]','[b,b,b]'] 还有我生成的其他地方 X2=[[a,a,a],[b,b,b]] 当我想添加这两个列表然
我试图使用递归将两个整数相乘,并意外编写了这段代码: //the original version int multiply(int a, int b) { if ( !b ) retu
我有一个列表中数字之间所有可能的操作组合: list = ['2','7','8'] 7+8*2 8+7*2 2*8+7 2+8*7 2-8*7 8-2/7 etc 我想知道是否可以说像 ('7*2+
我是一名优秀的程序员,十分优秀!