03工廠模式案例

下面我們來看下工廠模式案例

首先我們看pygame實現(xiàn)的一個案例:
按下s鍵或c鍵切換顯示圓形與方形,按上下左右鍵移動圖形斗忌,調(diào)用者main_01直接操作類實現(xiàn)的

import pygame

class Shape:
    def __init__(self,x,y,screen):
        self.screen=screen
        self.x=x
        self.y=y

    def draw(self):
        raise NotImplementedError()

    def move(self,direction):
        if direction=='up':
            self.y-=4
        elif direction=='down':
            self.y+=4
        elif direction=='left':
            self.x-=4
        elif direction=='right':
            self.x+=4

class Square(Shape):
    def draw(self):
        pygame.draw.rect(
            self.screen,
            (255,255,0),
            pygame.Rect(self.x,self.y,20,20)
        )

class Circle(Shape):
    def draw(self):
        pygame.draw.circle(
            self.screen,
            (0,255,255),
            (self.x,self.y),
            10
        )

def main_01():
    window_dimesions=800,600
    screen=pygame.display.set_mode(window_dimesions)
    obj=Square(100,100,screen)

    play_quits=False
    while not play_quits:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                play_quits=True

        pressed=pygame.key.get_pressed()
        if pressed[pygame.K_UP]:
            obj.move('up')
        elif pressed[pygame.K_DOWN]:
            obj.move('down')
        elif pressed[pygame.K_LEFT]:
            obj.move('left')
        elif pressed[pygame.K_RIGHT]:
            obj.move('right')
        elif pressed[pygame.K_c]:
            obj=Circle(100,100,screen)
        elif pressed[pygame.K_s]:
            obj=Square(100,100,screen)

        screen.fill((0,0,0))
        obj.draw()

        pygame.display.flip()

if __name__=="__main__":
    main_01()

下面我們改寫一下這個案例闯第,利用工廠方法逢渔。
將具體圖形類的創(chuàng)建交給工廠方法,我們主邏main_01只需要調(diào)用工廠方法來獲取圖形類的實例乡括,這樣萬一以后圖形類升級后創(chuàng)建圖形類變復雜了也不會讓圖形類使用者感到困難肃廓。
更重要的是這樣的好處是將圖形類與主邏輯main_01解耦合智厌,通過工廠來對類創(chuàng)建,管理和控制盲赊,往后圖形的的增加或者升級我們只需要修改工廠方法的內(nèi)部實現(xiàn)铣鹏,無需過多修改main_01的代碼

import pygame

class Shape:
    def __init__(self,x,y,screen):
        self.x=x
        self.y=y
        self.screen=screen

    def draw(self):
        raise NotImplementedError()

    def move(self,direction):
        if direction=='up':
            self.y-=4
        elif direction=='down':
            self.y+=4
        elif direction=='left':
            self.x-=4
        elif direction=='right':
            self.x+=4

    @staticmethod
    def factory(type,screen):
        if type=='circle':
            return Circle(100,100,screen)
        elif type=='square':
            return Square(100,100,screen)

class Square(Shape):
    def draw(self):
        pygame.draw.rect(
            self.screen,
            (255,255,0),
            pygame.Rect(self.x,self.y,20,20)
        )

class Circle(Shape):
    def draw(self):
        pygame.draw.circle(
            self.screen,
            (0,255,255),
            (self.x,self.y),
            10
        )

def main_01():
    window_dimesionts=800,600
    screen=pygame.display.set_mode(window_dimesionts)
    obj=Shape.factory('square',screen)
    player_quits=False

    while not player_quits:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                player_quits=True

            pressed=pygame.key.get_pressed()
            if pressed[pygame.K_UP]:
                obj.move('up')
            elif pressed[pygame.K_DOWN]:
                obj.move('down')
            elif pressed[pygame.K_LEFT]:
                obj.move('left')
            elif pressed[pygame.K_RIGHT]:
                obj.move('right')
            elif pressed[pygame.K_c]:
                # obj=Circle(100,100,screen)
                obj=Shape.factory('circle',screen)
            elif pressed[pygame.K_s]:
                # obj=Square(100,100,screen)
                obj=Square.factory('square',screen)

            screen.fill((0,0,0))
            obj.draw()

        pygame.display.flip()

if __name__=="__main__":
    main_01()

下面再看另一個案例,利用抽象工廠哀蘑,利用抽象工廠的抽象方法來規(guī)范工廠的接口

'''
抽象工廠模式 
根據(jù)用戶輸入age的不同诚卸,創(chuàng)建不同的工廠,然后通過工廠創(chuàng)建處理具體對象用來處理事件
'''
import abc
#先抽象出對象接口绘迁,讓創(chuàng)建出來的對象符合標準
class Hero_Abstract(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def interact_with(self,obstacle):
        pass
class Obstacle_Abstract(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def action(self):
        pass
#再抽象出工廠的借口合溺,讓工廠能符合協(xié)議的方式生成對象
class World_Base(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def make_character(self):
        pass

    @abc.abstractmethod
    def make_obstacle(self):
        pass

#-------------------青蛙游戲,專供0~11歲兒童
#青蛙是Hero單位
class Forg(Hero_Abstract):
    def __init__(self,name):
        self.name=name

    def __str__(self):
        return self.name

    def interact_with(self,obstacle):
        print("{} th the frog encounters {} and {}!".format(self,obstacle,obstacle.action()))

#Bug是obstacle單位
class Bug(Obstacle_Abstract):
    def __str__(self):
        return 'a bug'

    def action(self):
        return 'eats it'

#FrogWorld是World單位
class FrogWorld(World_Base):
    def __init__(self,name):
        print(self)
        self.player_name=name

    def __str__(self):
        return "\n\n\t------ Frog World ------"

    def make_character(self):
        return Forg(self.player_name)

    def make_obstacle(self):
        return Bug()

#-------------------巫師游戲缀台,專供11歲往上兒童
#wizard是hero單位
class Wizard(Hero_Abstract):
    def __init__(self,name):
        self.name=name

    def __str__(self):
        return self.name

    def interact_with(self,obstacle):
        print("{} the Wizard batteles against {} and {}!".format(self,obstacle,obstacle.action()))

#ork是obstacle單位
class Ork(Obstacle_Abstract):
    def __str__(self):
        return 'an evial ork'

    def action(self):
        return 'kills it'

#Wizard是WordBase單位
class WizardWorld(World_Base):
    def __init__(self,name):
        print(self)
        self.player_name=name

    def __str__(self):
        return '\n\n\t------ Wizard World ------'

    def make_character(self):
        return Wizard(self.player_name)

    def make_obstacle(self):
        return Ork()

#游戲入口
class GameEnvironment:
    def __init__(self,factory):
        self.hero=factory.make_character()
        self.obstacle=factory.make_obstacle()

    def play(self):
        self.hero.interact_with(self.obstacle)

def validate_age(name):
    try:
        age=input('Welcome {}. How old are you?:'.format(name))
        age=int(age)
    except Exception as e:
        print("Age {} is valid, plz try again...Try again".format(age))
        return (False,age)
    return (True,age)

def main01():
    name=input("Hello. what's your name?:")
    valid_input=False
    while not valid_input:
        valid_input,age=validate_age(name)
        game=FrogWorld if age<18 else WizardWorld
        environment=GameEnvironment(game(name))
        environment.play()

if __name__=="__main__":
    main01()

我們再來看個例子棠赛,按下1,2,3,4,5,6沿著對角線從左上方向右下方顯示特定圖案

#demo03的升級版,采用抽閑方法構(gòu)成抽象工廠規(guī)范代碼
import pygame
import abc

#抽象工廠
class Factory_Abstractory(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def make_object(self,x,y,object_class_name):
        pass

#圖形對象基類
class Base_Object(metaclass=abc.ABCMeta):
    def __init__(self,x,y):
        self.x=x
        self.y=y

    def move(self,direction):
        if direction=='up':
            self.y-=4
        elif direction=='down':
            self.y+=4
        elif direction=='left':
            self.x-=4
        elif direction=='right':
            self.x+=4

    #繪制圖形
    @abc.abstractmethod
    def draw(self,screen):
        pass

#小圓
class Circle_Small(Base_Object):
    def draw(self,screen):
        screen.fill((0,0,0))
        pygame.draw.circle(
            screen,
            (0, 255, 255),
            (self.x, self.y),
            8
        )
#園
class Circle(Base_Object):
    def draw(self,screen):
        screen.fill((0,0,0))
        pygame.draw.circle(
            screen,
            (0, 255, 255),
            (self.x, self.y),
            15
        )
#大圓
class Circle_Big(Base_Object):
    def draw(self,screen):
        screen.fill((0,0,0))
        pygame.draw.circle(
            screen,
            (0, 255, 255),
            (self.x, self.y),
            25
        )
#正方形
class Square(Base_Object):
    def draw(self,screen):
        screen.fill((0,0,0))
        pygame.draw.rect(
            screen,
            (255,255,0),
            pygame.Rect(self.x,self.y,20,20)
        )
#長方形(x向長度大于y向長度)
class Square_Low(Base_Object):
    def draw(self,screen):
        screen.fill((0,0,0))
        pygame.draw.rect(
            screen,
            (255,255,0),
            pygame.Rect(self.x,self.y,50,20)
        )
#長方形(x向長度小于y向長度)
class Square_High(Base_Object):
    def draw(self,screen):
        screen.fill((0,0,0))
        pygame.draw.rect(
            screen,
            (255,255,0),
            pygame.Rect(self.x,self.y,20,50)
        )

#方形工廠與圓形工廠
class Square_Factory(Factory_Abstractory):
    def make_object(self,x,y,object_class_name):
        if object_class_name=='s':
            return Square(x,y)
        elif object_class_name=='sl':
            return Square_Low(x,y)
        elif object_class_name=='sh':
            return Square_High(x,y)
class Circle_Factory(Factory_Abstractory):
    def make_object(self,x,y,object_class_name):
        if object_class_name=='c':
            return Circle(x,y)
        elif object_class_name=='cs':
            return Circle_Small(x,y)
        elif object_class_name=='cb':
            return Circle_Big(x,y)

def draw_object_function(factory,x,y,object_name,screen):
    obj=factory.make_object(x,y,object_name)
    obj.draw(screen)


def main_01():
    window_dimesions=900,900
    screen=pygame.display.set_mode(window_dimesions)
    sq_factory=Square_Factory()
    ci_factory=Circle_Factory()

    play_quits=False


    while not play_quits:
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                play_quits=True

        pressed=pygame.key.get_pressed()
        if pressed[pygame.K_1]:
            draw_object_function(sq_factory,100,100,'s',screen)
        elif pressed[pygame.K_2]:
            draw_object_function(sq_factory,150,150,'sl',screen)
        elif pressed[pygame.K_3]:
            draw_object_function(sq_factory,200,200,'sh',screen)
        elif pressed[pygame.K_4]:
            draw_object_function(ci_factory,250,250,'c',screen)
        elif pressed[pygame.K_5]:
            draw_object_function(ci_factory,300,300,'cs',screen)
        elif pressed[pygame.K_6]:
            draw_object_function(ci_factory,350,350,'cb',screen)

        pygame.display.flip()

if __name__=='__main__':
    main_01()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膛腐,一起剝皮案震驚了整個濱河市睛约,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哲身,老刑警劉巖辩涝,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異勘天,居然都是意外死亡怔揩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門脯丝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來沧踏,“玉大人,你說我怎么就攤上這事巾钉。” “怎么了秘案?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵砰苍,是天一觀的道長。 經(jīng)常有香客問我阱高,道長赚导,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任赤惊,我火速辦了婚禮吼旧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘未舟。我一直安慰自己圈暗,他們只是感情好掂为,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著员串,像睡著了一般勇哗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上寸齐,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天欲诺,我揣著相機與錄音,去河邊找鬼渺鹦。 笑死扰法,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的毅厚。 我是一名探鬼主播塞颁,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼卧斟!你這毒婦竟也來了殴边?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤珍语,失蹤者是張志新(化名)和其女友劉穎锤岸,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體板乙,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡是偷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了募逞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛋铆。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖放接,靈堂內(nèi)的尸體忽然破棺而出刺啦,到底是詐尸還是另有隱情,我是刑警寧澤纠脾,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布玛瘸,位于F島的核電站,受9級特大地震影響苟蹈,放射性物質(zhì)發(fā)生泄漏糊渊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一慧脱、第九天 我趴在偏房一處隱蔽的房頂上張望渺绒。 院中可真熱鬧,春花似錦、人聲如沸宗兼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽针炉。三九已至挠他,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間篡帕,已是汗流浹背殖侵。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留镰烧,地道東北人拢军。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像怔鳖,于是被迫代替她去往敵國和親茉唉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容