7.設計模式之五:建造者模式【建立型模式】

在軟件開發過程當中有時須要建立一個複雜的對象,這個複雜對象一般由多個子部件按必定的步驟組合而成。如遊戲中的不一樣角色,其性別、個性、能力、臉型、體型、服裝、髮型等特性都有所差別;還有汽車中的方向盤、發動機、車架、輪胎等部件也多種多樣;每封電子郵件的發件人、收件人、主題、內容、附件等內容也各不相同。python

以上全部這些產品都是由多個部件構成的,各個部件能夠靈活選擇,但其建立步驟都大同小異。這類產品的建立沒法用前面介紹的工廠模式描述,只有建造者模式能夠很好地描述該類產品的建立。算法

定義與特色

建造者(Builder)模式的定義:指將一個複雜對象的構造與它的表示分離,使一樣的構建過程能夠建立不一樣的表示,這樣的設計模式被稱爲建造者模式。設計模式

它是將一個複雜的對象分解爲多個簡單的對象,而後一步一步構建而成。它將變與不變相分離,即產品的組成部分是不變的,但每一部分是能夠靈活選擇的。佈局

該模式的主要優勢以下:ui

  1. 各個具體的建造者相互獨立,有利於系統的擴展。
  2. 客戶端沒必要知道產品內部組成的細節,便於控制細節風險。

其缺點以下:spa

  1. 產品的組成部分必須相同,這限制了其使用範圍。
  2. 若是產品的內部變化複雜,該模式會增長不少的建造者類。

建造者(Builder)模式和工廠模式的關注點不一樣:建造者模式注重零部件的組裝過程,而工廠方法模式更注重零部件的建立過程,但二者能夠結合使用。設計

結構與實現

建造者(Builder)模式由產品、抽象建造者、具體建造者、指揮者等 4 個要素構成,如今咱們來分析其基本結構和實現方法。code

1. 模式的結構

建造者(Builder)模式的主要角色以下。對象

  1. 產品角色(Product):它是包含多個組成部件的複雜對象,由具體建造者來建立其各個部件。
  2. 抽象建造者(Builder):它是一個包含建立產品各個子部件的抽象方法的接口,一般還包含一個返回複雜產品的方法 getResult()。
  3. 具體建造者(Concrete Builder):實現 Builder 接口,完成複雜產品的各個部件的具體建立方法。
  4. 指揮者(Director):它調用建造者對象中的部件構造與裝配方法完成複雜對象的建立,在指揮者中不涉及具體產品的信息。

 

2. 模式的實現

上圖給出了建造者(Builder)模式的主要結構,其相關類的代碼以下。blog

(1) 產品角色:包含多個組成部件的複雜對象。

class Product(object):
    '''產品類'''
    __part_a = ""
    __part_b = ""
    __part_c = ""

    @property
    def part_a(self):
        return self.__part_a

    @part_a.setter
    def part_a(self, a):
        self.__part_a = a

    @property
    def part_b(self):
        return self.__part_b

    @part_b.setter
    def part_b(self, b):
        self.__part_b = b

    @property
    def part_c(self):
        return self.__part_c

    @part_c.setter
    def part_c(self, c):
        self.__part_c = c

    def show(self):
        '''顯示產品特性'''
        print(self.__part_a)
        print(self.__part_b)
        print(self.__part_c)

 (2) 抽象建造者:包含建立產品各個子部件的抽象方法。

class AbstractBuilder(object):
    '''抽象建造者'''
    product = Product()

    def build_part_a(self):
        '''抽象方法'''
        pass

    def build_part_b(self):
        '''抽象方法'''
        pass

    def build_part_c(self):
        '''抽象方法'''
        pass

    def get_result(self):
        return self.product

 (3) 具體建造者:實現了抽象建造者接口。

class ConcreteBuilder1(AbstractBuilder):
    '''具體建造者'''
    def build_part_a(self):
        self.product.part_a = "Builder1 建造 PartA"

    def build_part_b(self):
        self.product.part_b = "Builder1 建造 PartB"

    def build_part_c(self):
        self.product.part_c = "Builder1 建造 PartC"


class ConcreteBuilder2(AbstractBuilder):
    def build_part_a(self):
        self.product.part_a = "Builder2 建造 PartA"

    def build_part_b(self):
        self.product.part_b = "Builder2 建造 PartB"

    def build_part_c(self):
        self.product.part_c = "Builder2 建造 PartC"

(4) 指揮者:調用建造者中的方法完成複雜對象的建立。

class Director(object):
    _builder = None  # Type -> Builder

    def __init__(self, builder):
        self._builder = builder

    def construct(self):
        '''產品的構建與組裝'''
        self._builder.build_part_a()
        self._builder.build_part_b()
        self._builder.build_part_c()
        return self._builder.get_result()

(5) 客戶類。

if __name__ == '__main__':
    builder = ConcreteBuilder1()
    director = Director(builder)
    product = director.construct()
    product.show()

 運行結果:

Builder1 建造 PartA
Builder1 建造 PartB
Builder1 建造 PartC

應用實例

【例1】用建造者(Builder)模式描述客廳裝修。

分析:客廳裝修是一個複雜的過程,它包含牆體的裝修、電視機的選擇、沙發的購買與佈局等。客戶把裝修要求告訴項目經理,項目經理指揮裝修工人一步步裝修,最後完成整個客廳的裝修與佈局,因此本實例用建造者模式實現比較適合。

這裏客廳是產品,包括牆、電視和沙發等組成部分具體裝修工人是具體建造者,他們負責裝修與牆、電視和沙發的佈局。項目經理是指揮者,他負責指揮裝修工人進行裝修。

class Parlour(object):
    '''客廳類'''
    __wall = ""
    __TV = ""
    __sofa = ""

    @property
    def wall(self):
        return self.__wall

    @wall.setter
    def wall(self, wall):
        self.__wall = wall

    @property
    def TV(self):
        return self.__TV

    @TV.setter
    def TV(self, TV):
        self.__TV = TV

    @property
    def sofa(self):
        return self.__sofa

    @sofa.setter
    def sofa(self, sofa):
        self.__sofa = sofa

    def show(self):
        print(self.__wall)
        print(self.__TV)
        print(self.__sofa)

class AbstractDecorator(object):
    '''抽象裝修工人類'''
    parlour = Parlour()
    def build_wall(self):
        pass

    def build_TV(self):
        pass

    def build_sofa(self):
        pass

    def get_result(self):
        return self.parlour

class ConcreteDecorator1(AbstractDecorator):
    def build_wall(self):
        self.parlour.wall = "紅色牆"

    def build_TV(self):
        self.parlour.TV = "紅色電視"

    def build_sofa(self):
        self.parlour.sofa = "紅色沙發"


class ConcreteDecorator2(AbstractDecorator):
    def build_wall(self):
        self.parlour.wall = "藍色牆"

    def build_TV(self):
        self.parlour.TV = "藍色電視"

    def build_sofa(self):
        self.parlour.sofa = "藍色沙發"

class ProjrctManager(object):
    _decorator = None

    def __init__(self, decorator):
        self._decorator = decorator

    def construct(self):
        self._decorator.build_wall()
        self._decorator.build_TV()
        self._decorator.build_sofa()

        return self.__decorator.get_result()

if __name__ == '__main__':
    decorator = ConcreteDecorator1()
    manager = ProjrctManager(decorator)
    parlour = manager.construct()
    parlour.show()
紅色牆
紅色電視
紅色沙發

應用場景

建造者(Builder)模式建立的是複雜對象,其產品的各個部分常常面臨着劇烈的變化,但將它們組合在一塊兒的算法卻相對穩定,因此它一般在如下場合使用。

  • 建立的對象較複雜,由多個部件構成,各部件面臨着複雜的變化,但構件間的建造順序是穩定的。
  • 建立複雜對象的算法獨立於該對象的組成部分以及它們的裝配方式,即產品的構建過程和最終的表示是獨立的。

擴展

建造者(Builder)模式在應用過程當中能夠根據須要改變,若是建立的產品種類只有一種,只須要一個具體建造者,這時能夠省略掉抽象建造者,甚至能夠省略掉指揮者角色。

相關文章
相關標籤/搜索