加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 1 建造者模式
    • 2 實(shí)例
    • 總結(jié)
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

《大話設(shè)計(jì)模式》解讀09-建造者模式

2024/12/31 來源:wechat
358
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

上篇文章,介紹了《大話設(shè)計(jì)模式》的第12章——外觀模式。

本篇,來介紹《大話設(shè)計(jì)模式》的第13章——建造者模式。并通過python代碼實(shí)現(xiàn)示例代碼的功能。

1 建造者模式

建造者模式(Builder):將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。

建造者模式的類圖如下:

    Builder:抽象建造類,定義建造一個(gè)產(chǎn)品所需要必要部件。ConcreateBuilder:具體建造類,繼承于抽象建造類,對(duì)抽象建造類中定義的接口進(jìn)行實(shí)現(xiàn),以實(shí)現(xiàn)個(gè)性化特征的產(chǎn)品構(gòu)建。Product:具體產(chǎn)品,具體建造類依賴于具體產(chǎn)品,即建造要根據(jù)產(chǎn)品功能來進(jìn)行建造。Director:指揮者類,控制建造的過程,確保建造過程中必要部件都執(zhí)行了建造。

2 實(shí)例

背景:書中小故事,小菜和大鳥去飯店吃飯,分別點(diǎn)的炒面和炒飯,小菜的炒面吃著還不錯(cuò),大鳥的炒飯味道不夠,蛋也少。大鳥嘗了一下炒面,味道不錯(cuò),就又要了份炒面,結(jié)果,這炒面沒放鹽。。?;厝サ穆飞希篪B感慨,肯德基、麥當(dāng)勞能在中國(guó)發(fā)展的很好,大概是因?yàn)槠渲谱鬟^程規(guī)范嚴(yán)格,而中國(guó)的小吃,比如“魚香肉絲”,不同的店可以吃出各種不同的口味。

啟發(fā):小吃店吃的味道怎么樣,依賴于廚師。聯(lián)想依賴倒轉(zhuǎn)原則:抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象,由于吃的飯菜要依賴于廚師這樣的細(xì)節(jié),飯客就很被動(dòng)。而像KFC那樣,制作流程進(jìn)行抽象,具體放什么配料、烤多長(zhǎng)時(shí)間等細(xì)節(jié)依賴于這個(gè)抽象。

題目:根據(jù)流程的抽象原理,用代碼的形式來實(shí)現(xiàn)用程序畫不同體型的小人。

2.1 版本一:?jiǎn)为?dú)的類

版本一要實(shí)現(xiàn)畫一個(gè)瘦的小人和一個(gè)胖的小人,通過分別定義這兩個(gè)類來實(shí)現(xiàn)所需的功能。

2.1.1 瘦人和胖人類

這里通過Python編程來進(jìn)行實(shí)踐,使用pygame庫中提供畫圖接口進(jìn)行畫圖。

畫一個(gè)廋的小人(ThinPerson),需要畫出頭(一個(gè)橢圓)、身體(一個(gè)矩形)、兩個(gè)胳膊(線))、兩條腿(線)

import pygame, sys

WHITE = (255, 255, 255)
BLUE = (0, 0, 255)

pygame.init()
screen = pygame.display.set_mode((200, 200))
screen.fill(WHITE)
    
class ThinPerson:
    def draw_person(self):
        pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)
        pygame.draw.rect(screen,BLUE,(60, 50, 10, 50),1)
        pygame.draw.line(screen,BLUE,(60, 50),(40, 100),1)
        pygame.draw.line(screen,BLUE,(70, 50),(90, 100),1)
        pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)
        pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)

class FatPerson:
    def draw_person(self):
        pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)
        pygame.draw.ellipse(screen,BLUE,(45,50,40,50),1)
        pygame.draw.line(screen,BLUE,(50, 50),(30, 100),1)
        pygame.draw.line(screen,BLUE,(80, 50),(100, 100),1)
        pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)
        #pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)

畫一個(gè)胖的小人(FatPerson),也是類似的。不過這種方式,需要在編寫代碼的時(shí)候不要忘記小人的各個(gè)部分都要有,如果忘記了其中某些項(xiàng),如忘記了畫其中一條腿,最終畫出來的小人就是不完整的。

2.1.2 主函數(shù)

首先,實(shí)例化對(duì)應(yīng)的股票,

然后,就可以調(diào)用對(duì)應(yīng)的買入和賣出的接口了。

thinPerson = ThinPerson() 
thinPerson.draw_person()

while True:
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.update()

畫廋人的效果就是上面的那個(gè)圖,畫胖人的效果,如果忘記了畫其中一條腿,將是下面的效果:

2.2 版本二:建造者模式

為了避免每增加一個(gè)新的不同特點(diǎn)的畫小人的需求在實(shí)現(xiàn)時(shí),可能忘記畫小人的某一部分的問題,可以使用建造者模式。

畫小人使用建造者模式,需要定義一個(gè)抽象類PersonBuilder,并聲明畫小人的各個(gè)部分的接口(聲明為抽象接口,即繼承的子類必須對(duì)接口進(jìn)行對(duì)應(yīng)的實(shí)現(xiàn)),具體不同特征的小人,各個(gè)部分的具體畫法是怎樣的,由具體建造者如畫瘦人的ThinPersonBuilder和畫胖人的FatPersonBuilder來進(jìn)行各自的實(shí)現(xiàn)。

為了能確保不過是畫廋人還是畫胖人,各個(gè)部分都能畫出而不遺漏,還需要一個(gè)指揮者PersonDirector,用它來控制建造過程。控制的原理是由它提供一個(gè)draw_person的接口,其內(nèi)部統(tǒng)一進(jìn)行繪制小人身體的各個(gè)部分。

修改后的代碼如下:

class PersonBuilder(ABC):
    @abstractmethod
    def build_head(self):
        pass

    @abstractmethod
    def build_body(self):
        pass

    @abstractmethod
    def build_arm_left(self):
        pass

    @abstractmethod
    def build_arm_right(self):
        pass

    @abstractmethod
    def build_leg_left(self):
        pass

    @abstractmethod
    def build_leg_right(self):
        pass

class PersonDirector():
    def __init__(self,personBuilder):
        self.pb = personBuilder

    def draw_person(self):
        self.pb.build_head()
        self.pb.build_body()
        self.pb.build_arm_left()
        self.pb.build_arm_right()
        self.pb.build_leg_left()
        self.pb.build_leg_right()
    
class ThinPersonBuilder(PersonBuilder):
    def build_head(self):
        pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)

    def build_body(self):
        pygame.draw.rect(screen,BLUE,(60, 50, 10, 50),1)

    def build_arm_left(self):
        pygame.draw.line(screen,BLUE,(60, 50),(40, 100),1)

    def build_arm_right(self):
        pygame.draw.line(screen,BLUE,(70, 50),(90, 100),1)

    def build_leg_left(self):
        pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)

    def build_leg_right(self):
        pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)

class FatPersonBuilder(PersonBuilder):
    def build_head(self):
        pygame.draw.ellipse(screen,BLUE,(50,20,30,30),1)

    def build_body(self):
        pygame.draw.ellipse(screen,BLUE,(45,50,40,50),1)

    def build_arm_left(self):
        pygame.draw.line(screen,BLUE,(50, 50),(30, 100),1)

    def build_arm_right(self):
        pygame.draw.line(screen,BLUE,(80, 50),(100, 100),1)

    def build_leg_left(self):
        pygame.draw.line(screen,BLUE,(60, 100),(45, 150),1)
"""
    def build_leg_right(self):
        pygame.draw.line(screen,BLUE,(70, 100),(85, 150),1)
"""
            
thinPerson = ThinPersonBuilder()
#fatPerson = FatPersonBuilder()
personDirector = PersonDirector(thinPerson)
personDirector.draw_person()

使用建造者模式后,因?yàn)槔L制小人的各個(gè)部分是由指揮者PersonDirector來控制繪制的,因此不會(huì)出現(xiàn)某個(gè)部位的繪制遺漏,如果某個(gè)具體建造者忘記了對(duì)其某個(gè)部分的繪制進(jìn)行重寫,在編譯運(yùn)行時(shí)就會(huì)報(bào)錯(cuò),例如畫胖人時(shí)忘記了畫右腿:

總結(jié)

本篇介紹了設(shè)計(jì)模式中的建造者模式,并通過畫小人的實(shí)例,使用Python編程,來演示建造者模式的使用。

文章推薦

《大話設(shè)計(jì)模式》解讀01-簡(jiǎn)單工廠模式

《大話設(shè)計(jì)模式》解讀02-策略模式

《大話設(shè)計(jì)模式》解讀03-裝飾模式

《大話設(shè)計(jì)模式解讀》04-代理模式

《大話設(shè)計(jì)模式》解讀05-工廠方法

《大話設(shè)計(jì)模式》解讀06-原型模式

《大話設(shè)計(jì)模式》解讀07-模板方法

《大話設(shè)計(jì)模式》解讀08-外觀模式

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計(jì)資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄