創建型模式---工廠模式

工廠模式

在工廠設計模式中,客戶端可以請求一個對象,而無需要知道這個對象來自哪里,也就是使用哪個類來生成這個對象。工廠背后的思想是簡化對象的創建。與客戶端自己基于類實例化直接創建對象相比,基于一個中心化函數來實現,更易于追蹤創建了那些對象。
工廠通常有兩種形式:一種是工廠方法,它是一個方法(函數),對不同的輸入參數返回不同的對象;第二種是抽象工廠,它是一組用于創建一系列相關事物對象的工廠方法。

工廠方法

在工廠方法模式中,我們執行單個函數,傳入一個參數(提供信息表明我們想要什么),但不要求直到任何關于對象如何實現以及對象來自哪里的細節。
現實生活中的例子:塑料玩具制造制造塑料玩具的壓塑粉都是一樣的,但是使用不同塑料模具就能產出不同的外形。比如有一個工廠方法,輸入是目標外形的名稱,輸出則是要求的塑料外形。
軟件中的例子:Django框架使用工廠方法模式來創建表單字段。Django的forms模塊支持不同種類字段(CharField,EmailField)的創建和制定(max_length,required)。
應用案例:
如果因為應用創建對象的代碼分布在多個不同的地方,而不是僅在一個函數/方法中,你發現沒法跟蹤這些對象,那么應該考慮使用工廠方法模式。工廠方法集中地在一個地方創建對象,使對象跟蹤變得更容易。

案例實現

以下例子將關注兩種流行的人類可讀文件格式:XML和JSON。
在當前這個問題中,我們有一些輸入數據存儲在一個XML文件和JSON文件中,要對這兩個文件進行解析,獲取一些信息。同時,希望對這些(以及將來涉及的的所有)外部服務進行集中式的客戶端連接。我們使用工廠方法來解決這個問題。
#數據來源:
json文件:http://opensource.adobe.com/Spry/samples/data_region/JSONDataSetSample.html#Example4
xml文件:https://en.wikipedia.org/wiki/JSON#XML
import xml.etree.ElementTree as etree
import json#類JSONConnector解析JSON文件,通過parsed_data()方法以一個字典dict的形式返回數據
class JSONConnector:def __init__(self,filepath):self.data = {}with open(filepath,mode='r',encoding='utf-8') as f:self.data = json.load(f)@propertydef parsed_data(self):return self.data#類XMLConnector解析XML文件,通過parsed_data()方法以xml.etree.Element列表的形式返回所有數據。
class XMLConnector:def __init__(self,filepath):self.tree = etree.parse(filepath)@propertydef parsed_data(self):return self.tree#工廠方法connect_factory,基于輸入路徑的擴展名返回一個JSONConnector或XMLConnector的實例
def connect_factory(filepath):if filepath.endswith('json'):connector = JSONConnectorelif filepath.endswith('xml'):connector = XMLConnectorelse:raise ValueError('Cannot connect to {}'.format(filepath))return connector(filepath)#函數connnect_to對工廠方法進行包裝,添加了異常處理
def connect_to(filepath):factory = Nonetry:factory = connect_factory(filepath)except ValueError as e:print(e)return factorydef main():sqlite_factory = connect_to('person.sq3')print()xml_factory = connect_to('test2.xml')xml_data = xml_factory.parsed_dataliars = xml_data.findall(".//{}[{}='{}']".format('person','lastName','Liar'))for liar in liars:print('first name:{}'.format(liar.find('firstName').text))print('last name:{}'.format(liar.find('lastName').text))[print('phone number ({}):'.format(p.text)) for p in liar.find('phoneNumber')]#待完善XML模式匹配語法print()json_factory = connect_to('test1.json')json_data = json_factory.parsed_dataprint('found:{} donuts'.format(len(json_data)))for donut in json_data:print('name:{}'.format(donut['name']))print('price:${}'.format(donut['ppu']))[print('topping:{}{}'.format(t['id'],t['type'])) for t in donut['topping']]if __name__ == '__main__':main()

抽象工廠

抽象工廠設計模式是抽象方法的一種泛化。概括來說,一個抽象工廠是(邏輯上的)一組工廠方法,其中每個工廠方法負責產生不同種類的對象。
現實生活中的例子:汽車制造業應用了抽象工廠的思想。沖壓不同汽車模型的部件(車門、儀表盤、車篷以及擋泥板的等)所使用的的機件是相同的。機件組裝起來的模型隨時可配置,且易于改變。
軟件中的例子:程序包django_factory是一個用于在測試中創建Django模型的抽象工廠實現,可用來為支持測試專有屬性的模型創建實例。這能讓測試代碼的可讀性更高,且能避免共享不必要的代碼,故有其存在的價值。
應用案例:
抽象工廠模式是工廠方法模式的一種泛化,所以它能提供相同的好處:讓對象的創建更容易追蹤;將對象創建與使用解耦;提供優化內存占用和應用性能的潛力。
那我們何時使用工廠方法,何時又該使用抽象工廠?答案是,通常一開始使用工廠方法,因為它更簡單。如果后來發現應用需要許多工廠方法,那么會將創建一些列對象的過程合并在一起更合理,從而最終引入抽象工廠。
#想象一下,我們正在創造一個游戲,或者想在應用中包含一個迷你游戲讓用戶娛樂一下。我們希望至少包含兩個游戲,一個面向孩子,一個面向大人。在運行時,基于用戶輸入,決定該創建那個游戲并運行。游戲的創建部分由一個抽象工廠維護。
class Frog:def __init__(self,name):self.name = namedef __str__(self):return self.namedef interact_with(self,obstacle):print('{} the Frog encounters {} and {}!'.format(self,obstacle,obstacle.action()))class Bug:def __str__(self):return 'a bug'def action(self):return 'eats it'#抽象工廠FrogWorld,其主要職責是創建游戲的主人公和障礙物。
class FrogWorld:def __init__(self,name):print(self)self.player_name = namedef __str__(self):return '\n\n\t------ Frog World ------'def make_character(self):return Frog(self.player_name)def make_obstacle(self):return Bug()class Wizard:def __init__(self,name):self.name = namedef __str__(self):return self.namedef interact_with(self,obstacle):print('{} the wizard battles against {} and {}!'.format(self,obstacle,obstacle.action()))class Ork:def __str__(self):return 'a evil ork'def action(self):return 'kills it'#抽象工廠WizardWorld,類似于FrogWorld
class WizardWorld:def __init__(self,name):print(self)self.player_name = namedef __str__(self):return '\n\n\t------ Wizard World ------'def make_character(self):return Wizard(self.player_name)def make_obstacle(self):return Ork()#類GameEnvironment是我們游戲的主入口,它接受factory作為輸入,用其創建游戲的世界。
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)#validate_age提示用戶輸入一個有效的年齡
def validate_age(name):try:age = input('Welcome {}.How old are you?'.format(name))age = int(age)except ValueError as err:print("Age {} is invalid,please try again...".format(age))return (False,age)return (True,age)def main():name = input("Hello,What's your name?")valid_input = Falsewhile not valid_input:valid_input,age = validate_age(name)game = FrogWorld if age<18 else WizardWorldenvironment = GameEnvironment(game(name))environment.play()if __name__ == '__main__':main()

小結

工廠方法設計模式的實現是一個不屬于任何類的單一函數,負責單一種類對象的創建。
抽象工廠設計模式的實現是同屬于單個類的許多個工廠方法用于創建一系列種類的相關對象。

?

轉載于:https://www.cnblogs.com/xiaoshayu520ly/p/10978424.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448809.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448809.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448809.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenCL memory object 之 Global memory (2)

當我們用clCreateBuffer, clCreateImage創建OpenCL memory object時候&#xff0c;我們需要輸入一個flag參數&#xff0c;這個參數決定memory object的位置。 cl_mem clCreateBuffer (cl_context context, cl_mem_flags flags, size_t size, void *host_ptr, cl_int *errc…

數據結構進階篇-跳表

大家想必都知道&#xff0c;數組和鏈表的搜索操作的時間復雜度都是O(N)的&#xff0c;在數據量大的時候是非常耗時的。對于數組來說&#xff0c;我們可以先排序&#xff0c;然后使用二分搜索&#xff0c;就能夠將時間復雜度降低到O(logN)&#xff0c;但是有序數組的插入是一個O…

查看本機ssh公鑰,生成公鑰

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 查看ssh公鑰方法&#xff1a; 1.通過命令窗口&#xff1a;打開你的git bash 窗口&#xff0c;進入.ssh目錄&#xff1a;cd ~/.ssh&…

如何實現動態水球圖 --》 echars結合echarts-liquidfill實現

1&#xff09;項目中作為項目依賴&#xff0c;安裝到項目當中(注意必須要結合echars) npm install echarts vue-echarts --save npm install echarts-liquidfill --save 2&#xff09;在需要使用水晶球的組件里引入liquidFill.js import echarts-liquidfill/src/liquidFill.js;…

OpenCL memory object 之選擇傳輸path

對應用程序來說&#xff0c;選擇合適的memory object傳輸path可以有效提高程序性能。 下面先看一寫buffer bandwidth的例子&#xff1a; 1. clEnqueueWriteBuffer()以及clEnqueueReadBuffer() 如果應用程序已經通過malloc 或者mmap分配內存&#xff0c;CL_MEM_USE_HOST_PTR是個…

struts入門超詳細

https://blog.csdn.net/yerenyuan_pku/article/details/52652262轉載于:https://www.cnblogs.com/liuna369-4369/p/10870873.html

RabbitMQ 從入門到精通 (一)

目錄 1. 初識RabbitMQ2. AMQP3.RabbitMQ的極速入門4. Exchange(交換機)詳解4.1 Direct Exchange4.2 Topic Exchange4.3 Fanout Exchange5. Message 消息1. 初識RabbitMQ RabbitMQ 是一個開源的消息代理和隊列服務器&#xff0c;用來通過普通協議在完全不同的應用之間共享數據&a…

接收并解析消息體傳參、解析 json 參數

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1.場景&#xff1a;postman 發送了一個 post 請求&#xff0c;如下&#xff1a; 2. 解析方式為用一個 vo 對象來接收 json。把 json 中的…

OpenCL memory object 之 傳輸優化

首先我們了解一些優化時候的術語及其定義&#xff1a; 1、deferred allocation&#xff08;延遲分配&#xff09;&#xff0c; 在第一次使用memory object傳輸數據時&#xff0c;runtime才對memory object真正分配空間。 這樣減少了資源浪費&#xff0c;但第一次使用時要慢一些…

VBS使文本框的光標位于所有字符后

有時候在文本框里會顯示一部分提示信息&#xff0c;用戶在這些提示信息后面輸入文本&#xff0c;但是將焦點設置于文本框后&#xff0c;光標總是在文本框的最前面&#xff0c; 用戶輸入的時候需要按"-->"鍵將光標移到最后才能輸入&#xff0c;這樣的操作很不爽。我…

記錄ionic 最小化應用時所遇的問題

ionic3與ionic4最小化插件安裝不一樣&#xff1a; ionic3安裝方法&#xff1a; $ ionic cordova plugin add cordova-plugin-appminimize $ npm install --save ionic-native/app-minimize4 并在app.module.ts中 注入依賴&#xff1a; import { AppMinimize } from ionic-nativ…

解決 --- Docker 啟動時報錯:iptables:No chain/target/match by the name

問題&#xff1a;jenkins的docker containner啟動失敗&#xff0c;報錯&#xff1a;failed programming external connectivity … iptables: No chain/target/match by that name” docker 服務啟動的時候&#xff0c;docker服務會向iptables注冊一個鏈&#xff0c;以便讓dock…

AMD OpenCL 大學課程

AMD OpenCL大學課程是非常好的入門級OpenCL教程&#xff0c;通過看教程中的PPT&#xff0c;我們能夠很快的了解OpenCL機制以及編程方法。下載地址&#xff1a;http://developer.amd.com/zones/OpenCLZone/universities/Pages/default.aspx 教程中的英文很簡單&#xff0c;我相信…

第一篇 計算機基礎

1.什么是編程語言 python和中文、英語一樣、都是一門語言&#xff0c;只要是語言&#xff0c;其實就庫看成是一種事物與另一種事物溝通的介質。python屬于編程語言&#xff0c;編程語言是程序員與計算機之間溝通的介質&#xff1b;中文和英文則是人與人之間溝通的介質。 2.什么…

47.QT-QChart之曲線圖,餅狀圖,條形圖使用

1.使用準備 在pro中, 添加QT charts 然后在界面頭文件中添加頭文件并聲明命名空間,添加: #include <QtCharts> QT_CHARTS_USE_NAMESPACE 2.QChart之曲線圖 繪制曲線圖需要用到3個類 QSplineSeries: 用于創建有由一系列數據組成的曲線.類似的還有QPieSeries(餅圖數據). Q…

Docker 部署應用、jar 工程 docker 方式部署

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 把要部署的工程打成一個jar包。&#xff08;我的工程叫 gentle &#xff09; 打 jar 的方法&#xff1a;超簡單方法&#xff1a; Int…

流浪不是我的初衷 ... ...

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 或許&#xff0c;我從來就是一個習慣沉默的人 ... 或許&#xff0c;我從來就不善于傾述 ... 會有難過的時候&#xff0c;會有覺得累的…

第二階段沖刺(2)

1、整個項目預期的任務量 &#xff08;任務量 所有工作的預期時間&#xff09;和 目前已經花的時間 &#xff08;所有記錄的 ‘已經花費的時間’&#xff09;&#xff0c;還剩余的時間&#xff08;所有工作的 ‘剩余時間’&#xff09; &#xff1b; 所有工作的預期時間&#…

VS2008+OpenCL環境配置

1. 配置.cl文件支持: 1.1. 打開VS2008&#xff0c; 工具->選項->文本編輯器->文件擴展名&#xff0c;添加一個新的擴展名&#xff0c;指定編輯器為Microsoft Visual C 。這樣在OpenCL文件中就能顯示C的語法高亮了。 1.2. 配置OpenCL語法高亮 - 打開目錄~\NVIDIA Corpo…

第十二周學習進度報告

代碼時間&#xff1a;17小時左右&#xff0c; 代碼量&#xff1a;300行左右&#xff0c; 閱讀&#xff1a;一個app的誕生20頁&#xff1b;構建之法30頁 知識&#xff1a;抽象典型用戶&#xff08;具有代表性&#xff09;和場景&#xff0c;去設計相應功能。 轉載于:https://www…