【问题标题】:Builder pattern respecting the open-close principle遵循开闭原则的建造者模式
【发布时间】:2020-06-15 17:29:39
【问题描述】:

我有以下代码:

class Person:
    def __init__(self):
        # address
        street = None
        post_code = None
        city = None
        # empoyment
        company_name = None
        position = None


class PersonBuilder:

    def __init__(self, person=Person()):
        self.person = person

    def build(self):
        return self.person

    @property
    def works(self):
        return PersonJobBuilder(self.person)

    @property
    def lives(self):
        return PersonAddressBuilder(self.person)


class PersonJobBuilder(PersonBuilder):

    def __init__(self, person):
        super().__init__(person)

    def at(self, company):
        self.person.company_name = company
        return self


class PersonAddressBuilder(PersonBuilder):

    def __init__(self, person):
        super().__init__()

    def city(self, city):
        self.person.city = city
        return self

pb = PersonBuilder()

person = pb\
    .works \
        .at('Cora')\
    .lives \
        .city('Kandu')\
    .build()

上面的代码没有遵守开闭原则,因为每次我想添加一个新的构建器时,我都需要更改PersonBuilder类来添加livesworks等方法。

我知道可以使用继承,但是PersonAddressBuilderPersonJobBuilder 继承没有意义。

那么,还有哪些其他解决方案可用?

【问题讨论】:

  • 请详细说明为什么您认为这没有提供开闭原则。据我所知,您在问题中所说的与开放-封闭原则的任何一个流行定义都不相符。
  • 为什么不能在子类中扩展现有类并以这种方式添加方法?
  • @ChrisJohnson;如果我添加一个新的构建器,比如说“PersonPlayBuilder”,我必须更改“PersonBuilder”以添加返回“PersonPlay Builder”实例的函数“play”;为了尊重“关闭”原则,我不需要在每次需要添加新构建器时都更改“PersonBuilder”。
  • @martineau 我没有说我做不到,我说这没有意义。当然我可以做 PersonAddressBuilder(PersonJobBuilder) 并在主类中调用构建器,但是位置地址与工作没有直接关系,我认为这样做不符合逻辑。
  • 我理解你想要做什么,但这与开闭原则无关。您可以添加新的字段和方法:这意味着它实际上是开放的。现在你正在讨论最好/最方便的方法,这很公平。我会在这个意义上单独回应。

标签: python python-3.x design-patterns builder


【解决方案1】:

减少类之间依赖关系的一种典型方法是不使用继承,而是使用 mixin 模型。

这种方法与您喜欢的鸭子类型方法非常一致,代价是必须确保字段和方法名称不会在混入中重复——当范围很窄时,这不是问题;有时,当您设计 mixin 以供不同类重用时会出现问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-14
    • 2018-11-13
    • 2020-08-05
    • 2015-03-22
    • 2011-06-28
    • 2011-06-13
    • 1970-01-01
    • 2017-11-26
    相关资源
    最近更新 更多