設(shè)計模式之工廠模式—要的是工廠而不是作坊
工廠模式應(yīng)該是我們比較常用的設(shè)計模式之一,它提供了一種創(chuàng)建對象的最佳方式,在創(chuàng)建對象時不會對調(diào)用者暴露創(chuàng)建邏輯,調(diào)用者只需根據(jù)自己的需求獲取需要的對象,做到"拿來即用"。
說人話就是,我要什么,你就得給什么。
我們用生活中常用的支付來說明工廠模式的實現(xiàn)邏輯。我們在用手機支付的時候都會選擇支付方式,比如微信支付、支付寶支付,當(dāng)然還有其他的比如微付充支付、連連支付等等。用戶選擇了某一種支付方式,相應(yīng)的要生成支付的對象,執(zhí)行支付的方法,而這里支付對象的生成,我們交給工廠去做。
首先定義一個支付的抽象類:
抽象產(chǎn)品類
這個類的作用是標(biāo)準(zhǔn)化支付對象,規(guī)定好支付對象可以進行的操作,那就是下單。
然后就可以具體化我們的支付對象了,這里就以微信支付和支付寶支付為例:
微信支付產(chǎn)品類
支付寶支付產(chǎn)品類
有了具體的支付產(chǎn)品類,我們就可以創(chuàng)建工廠進行生產(chǎn)了,將微信支付和支付寶支付的支付對象給創(chuàng)建出來:
工廠類
很簡單,就是根據(jù)支付類型返回支付對象。
接下來做一個小測試,模擬下用戶支付,假設(shè)用戶選擇了微信支付:
測試方法
可以看到最終執(zhí)行了微信的下單方法。
OK,大功告成,可以下班啦!
但這真的是我們要的工廠模式嗎?
假如我們需要再加一種支付方式,比如連連支付,怎么整?簡單啊,再加個連連支付的產(chǎn)品類,工廠類里再加個if判斷,返回連連支付的對象,不就OK了嗎?
這樣是可以實現(xiàn)的。但如果我們在工廠類里進行擴展的時候,一不小心留個bug在里面,有可能會導(dǎo)致整個工廠類都不可用了,進而連帶著整個支付系統(tǒng)就不可用了,這樣顯然是不合理的。實際上,這樣的工廠模式違背了一個很重要的設(shè)計原則——開閉原則。開閉原則就是說,當(dāng)你在擴展程序的時候,不要改動原有代碼,要實現(xiàn)一個熱插拔的效果。
這種工廠模式實際上稱為簡單工廠模式,是一個管理混亂、雜亂無章的小作坊,而我們需要的,是一個井然有序、收放自如的現(xiàn)代化工廠。
所以,這就延伸出了另一種工廠模式——工廠方法模式。
既然在原有的工廠類上進行擴展是不合理的,那索性就把工廠類分開,一個支付一個工廠類,各自工廠類生產(chǎn)各自的支付對象,當(dāng)需要進行擴展的時候,只需新建自己的工廠類和支付產(chǎn)品類,而與其他的支付方式無關(guān),這樣就實現(xiàn)了熱插拔的效果。
于是我們的代碼可以演變?yōu)?,保留原有的支付抽象類和支付產(chǎn)品類,去掉工廠類,新建一個抽象工廠類,微信支付和支付寶支付各自實現(xiàn)其工廠類。
抽象工廠類
支付寶支付工廠類
微信支付工廠類
這樣就實現(xiàn)了工廠類的分離,微信支付工廠類負責(zé)生產(chǎn)微信支付的產(chǎn)品,支付寶支付工廠類負責(zé)生產(chǎn)支付寶支付的產(chǎn)品,所有工廠類各司其職,互不干擾。
測試一下:
這樣,工廠方法模式就實現(xiàn)了,這其實也是我們平時用的最多的模式,平時所說工廠模式實際就是指的工廠方法模式。當(dāng)然,工廠模式還有抽象工廠方法模式,這是比小作坊、小工廠更加高級的超級工廠模式,實現(xiàn)起來比較繁瑣,平時也基本用不到,這里就不細說了。