3

假设我有一个类层次结构。通过为实例提供额外的参数,我理论上可以通过单个类来维护其功能。这是一个例子(超级做作,但我想保持简单):

class Base:
  def __init__(self, a):
    self.a = a
  def f(self, x):
    raise NotImplemented # needs to be defined in subclass

class Mult(Base)
  def f(self, x):
    return self.a * x

class Add(Base):
  def f(self, x):
    return self.a + x

m = Mult(5)
a = Add(7)
m.f(10)
a.f(20)

上面的代码可以重构为:

class Compute:
  def __init__(self, a, func):
    self.a = a
    self.func = func
  def f(self, x)
    return self.func(self.a, x)

m = Compute(5, operator.mult)
a = Compute(7, operator.add)

我知道对于这个愚蠢的例子,它没有任何区别。所以除了理解我的观点,请不要考虑它。

我想知道在为现实生活中遇到的各种情况做出选择时应该考虑哪些因素?换句话说,使用类与参数化实例的优缺点是什么?

4

3 回答 3

1

在第一个示例中,您为客户端代码提供了执行一组固定操作的固定方式。乘法很容易,但如果你想除法,那就倒霉了。

在第二个示例中,您将实现细节推送到客户端。您现在拥有一个完整的与操作无关的计算框架。这需要对客户端代码有更多的了解。

所以,真正不同的是抽象的层次——你希望你的客户有多知识。如果它对所operator.mult使用的客户端很重要,而不是其他一些逻辑(例如,XML-RPC 到乘法服务器),那么第二个选项似乎是合适的。如果客户比您更了解如何处理这两个数字,并且您只想提供一个框架(某种包装器),那么第二种选择更好。如果你只是想让人们添加和增加东西,第一个选择更好。

于 2012-10-12T23:03:30.637 回答
1

这实际上取决于课程的作用。在您的示例中,类中的逻辑是如此之小,很明显您刚刚为方法提供了包装器作为类。拥有计算类更有意义。

在现实生活中,你应该问问自己你想要组合在一起的不同功能的凝聚力如何。虽然单一责任很重要,但你不需要接受那个荒谬的广告

于 2012-10-13T19:59:03.220 回答
0

我想这取决于您是否拥有有关转换(?)的所有信息,您将在构建时对可用的对象进行操作。如果你不这样做,你将很难调用更复杂的构造函数。

此外,在将其提交到某个路径之前,保留对“基本”对象执行操作的选项通常是有帮助的,即使在最初设计类时并不明显。

一般来说,我发现创建具有最少所需参数的构造函数并通过方法实现任何其他功能是最佳解决方案。

本着随机示例的精神,考虑:

参数化构造函数

class Image:
    # Some implementation

class Text:
    def __init__(self, image, whitelistChars):
        # This uses OCR to extract the text from an image then filters out 
        #   non-whitelisted characters
        #
        # image is an Image
        # whitelistChars is an interable containing characters that should 
        #   not be filtered out

im = Image('scan.tif')
t = Text(im, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ134567890');

基本构造函数

class Text:
    def __init__(self, image):
        # This uses OCR to extract the text from an image
        #
        # image is an Image


    def filter(self, whitelistChars):
        # This filters out non-whitelisted characters
        #
        # whitelistChars is an interable containing characters that should 
        #   not be filtered out

im = Image('scan.tif')
t = Text(im)
# <-- Are you interested in doing anything to the Text object t here?
t.filter('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ134567890')

在“基本构造函数”实现中,您可以选择在剥离非白名单字符之前使用该Text对象。t也许这有用?也许更重要的是,也许这在未来会有用?

如果您可以自信地说“不”,它没有用而且永远不会有用,那么我认为“参数化构造函数”很好。如果有的话,它消除了额外filter调用的需要。

但是,如果您希望重用代码,在转换它之前(在这种情况下过滤文本),保持打开选项来操作t,甚至只是检查它通常会很有帮助。

(我的 0.02 美元)

于 2012-10-12T23:00:45.400 回答