树的 Python 示例展示了复合模式和延迟初始化的最初想法。
class Node:
def __init__(self, val):
self._val = val
self._lchild = None
self._rchild = None
def set_lchild(self, node):
self._lchild = node
def set_rchild(self, node):
self._rchild = node
def sum(self):
sum = self._val
if self._lchild is not None:
sum += self._lchild.sum()
if self._rchild is not None:
sum += self._rchild.sum()
return sum
root = Node(1)
lchild = Node(2)
root.set_lchild(lchild)
root.sum()
为了避免空检查,引入了空对象模式。
class Node(ABC):
def __init__(self, val):
self._val = val
self._lchild = NullNode(0)
self._rchild = NullNode(0)
def set_lchild(self, node):
self._lchild = node
def set_rchild(self, node):
self._rchild = node
@abstractmethod
def is_null(self):
return NotImplemented
@abstractmethod
def sum(self):
return NotImplemented
class RegularNode(Node):
def is_null(self):
return False
def sum(self):
sum = self._val
if not self._lchild.is_null():
sum += self._lchild.sum()
if not self._rchild.is_null():
sum += self._rchild.sum()
return sum
class NullNode(Node):
def is_null(self):
return True
def sum(self):
return 0
root = RegularNode(1)
lchild = RegularNode(2)
root.set_lchild(lchild)
root.sum()
为了遵守里氏替换原则,对示例进行了修改。
class Node(ABC):
@abstractmethod
def is_null(self):
return NotImplemented
@abstractmethod
def sum(self):
return NotImplemented
class RegularNode(Node):
def __init__(self, val):
self._val = val
self._lchild = NullNode()
self._rchild = NullNode()
def set_lchild(self, node):
self._lchild = node
def set_rchild(self, node):
self._rchild = node
def is_null(self):
return False
def sum(self):
sum = self._val
if not self._lchild.is_null():
sum += self._lchild.sum()
if not self._rchild.is_null():
sum += self._rchild.sum()
return sum
class NullNode(Node):
def is_null(self):
return True
def sum(self):
return 0
root = RegularNode(1)
lchild = RegularNode(2)
root.set_lchild(lchild)
root.sum()
这使得
RegularNode
依赖于其兄弟 NullNode
。
而且我不确定该依赖关系是否违反了依赖倒置原则。
如果是这样,如何在不违反SOLID原则的情况下满足上述要求?
在上面的例子中,任何尝试都将违反 SOLID 原则。
最好的情况是不违反 SOLID 原则。 否则正常情况下哪个原则可以妥协?
空对象模式的重点是避免检查某些东西是否为空。所以
sum
的 RegularNode
方法就简单地变成了
def sum(self):
sum = self._val
sum += self._lchild.sum()
sum += self._rchild.sum()
return sum
这是有效的,因为
NullNode
的 sum
实现只是返回 0,就像你所做的那样。
is_null
方法消失了。基类 Node
中剩下的就是抽象方法 sum
。又漂亮又干净。