2

是否有描述以下设置的设计模式?这种设计是否存在任何重大问题?

Widget实例可以由“哑”构造函数Widget.__init__()或“智能”工厂方法构建Workbench.upgrade_widget()

class Widget:
  def __init__(self, abc, def, ...):
    self.abc = abc
    self.def = def
    ...
  ...

class Workbench:

  # widget factory function, which uses data from the workbench instance
  def upgrade_widget(self, widget, upgrade_info):
    widget = Widget(widget.abc, widget.def, ...)
    # I will modify the widget's attributes
    ...
    self.rearrange_widget(widget, xyz) # modifies widget's internal state
    ...
    widget.abc = ... # also modifies widget's state
    ...
    return widget

  # uses data from the workbench instance
  def rearrange_widget(self, widget, xyz):
    ...
  # this class does other stuff too
  ... 

小部件是不可变的,因为我不能在它们完全初始化后修改它的实例(很多代码都依赖于这个不变量)。但是我发现在初始化修改小部件非常方便,并且使代码更清晰。

我主要担心的是我修改了不同类中的“不可变”小部件。如果它只是 in upgrade_widget,我可能会接受它,因为它不会修改传递给它的小部件。但是该方法依赖于其他Workbench方法 ( rearrange_widget),这些方法会修改它作为参数接收的小部件。我觉得我正在失去对这个“不可变”实例实际可以修改的位置的控制——有人可能会不小心调用rearrange_widget一个已经完全初始化的小部件,从而导致灾难。

4

2 回答 2

1

@chees:一种更简洁的方法是修改并__dict__始终引发异常(顺便说一句,这不是一个好主意- 它只是一般):__init____setattr__raise Exception

class Widget:
    def __init__(self, args):
        self.__dict__['args'] = args

    def __setattr__(self, name, value):
        raise TypeError

在 Workbench 中以相同的方式修改它(即使用__dict__)不断提醒您您正在做一些您不应该做的事情。

于 2012-04-23T06:10:18.943 回答
1

您现在如何执行 Widget 的不变性?

如果您将“锁定”属性添加到您的小部件,并包装您的 setattr 以检查该属性怎么办:

class Widget(object):
    __locked = False
    def __init__(self,a,b,c,locked=True):
        ...
        self.__locked = locked

    def lock(self):
        self.__locked = True

    def is_locked(self):
        return self.__locked

    def __setattr___(self,*args,**kw):
        if self.__locked:
            raise Exception('immutable') # define your own rather than use Exception
        return super(Widget).__setattr__(self,*args,**kw)

然后在工厂:

class Workbench(object):
    def upgrade_widget(self,widget,upgrade_info):
        widget = Widget(widget.a,widget.b,...,locked=False)
        self.rearrange_widget(widget, blah)
        widget.c = 1337
        widget.lock()
        return widget

在一般使用中,您可以非常确定一旦锁定类不会发生任何有趣的事情。任何关心小部件不变性的方法也应该检查该小部件的 is_locked() 。例如,rearrange_widget 应该在做任何事情之前检查小部件是否也被解锁。

尽管恶意篡改了实例,但无论如何都可能发生这种情况。它也不会阻止属性被它们自己的方法改变。

请注意,我在上面编写的代码(伪 python)未经测试,但希望它说明了如何处理您的主要问题的总体思路。

哦,我不确定这种模式是否有特定的名称。

于 2012-04-23T04:50:46.087 回答