国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

抽象工廠模式(轉(zhuǎn))

2019-11-15 00:38:15
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
抽象工廠模式(轉(zhuǎn))這篇博文寫的很好,學(xué)習(xí)到了很多。本文轉(zhuǎn)載自http://m.survivalescaperooms.com/java-my-life/archive/2012/03/28/2418836.html場(chǎng)景問(wèn)題

  舉個(gè)生活中常見的例子——組裝電腦,我們?cè)诮M裝電腦的時(shí)候,通常需要選擇一系列的配件,比如CPU、硬盤、內(nèi)存、主板、電源、機(jī)箱等。為討論使用簡(jiǎn)單點(diǎn),只考慮選擇CPU和主板的問(wèn)題。

  事實(shí)上,在選擇CPU的時(shí)候,面臨一系列的問(wèn)題,比如品牌、型號(hào)、針腳數(shù)目、主頻等問(wèn)題,只有把這些問(wèn)題都確定下來(lái),才能確定具體的CPU。

  同樣,在選擇主板的時(shí)候,也有一系列問(wèn)題,比如品牌、芯片組、集成芯片、總線頻率等問(wèn)題,也只有這些都確定了,才能確定具體的主板。

  選擇不同的CPU和主板,是每個(gè)客戶在組裝電腦的時(shí)候,向裝機(jī)公司提出的要求,也就是我們每個(gè)人自己擬定的裝機(jī)方案。

  在最終確定這個(gè)裝機(jī)方案之前,還需要整體考慮各個(gè)配件之間的兼容性。比如:CPU和主板,如果使用Intel的CPU和AMD的主板是根本無(wú)法組裝的。因?yàn)镮ntel的CPU針腳數(shù)與AMD主板提供的CPU插口不兼容,就是說(shuō)如果使用Intel的CPU根本就插不到AMD的主板中,所以裝機(jī)方案是整體性的,里面選擇的各個(gè)配件之間是有關(guān)聯(lián)的。

  對(duì)于裝機(jī)工程師而言,他只知道組裝一臺(tái)電腦,需要相應(yīng)的配件,但是具體使用什么樣的配件,還得由客戶說(shuō)了算。也就是說(shuō)裝機(jī)工程師只是負(fù)責(zé)組裝,而客戶負(fù)責(zé)選擇裝配所需要的具體的配件。因此,當(dāng)裝機(jī)工程師為不同的客戶組裝電腦時(shí),只需要根據(jù)客戶的裝機(jī)方案,去獲取相應(yīng)的配件,然后組裝即可。

使用簡(jiǎn)單工廠模式的解決方案

  考慮客戶的功能,需要選擇自己需要的CPU和主板,然后告訴裝機(jī)工程師自己的選擇,接下來(lái)就等著裝機(jī)工程師組裝電腦了。

  對(duì)裝機(jī)工程師而言,只是知道CPU和主板的接口,而不知道具體實(shí)現(xiàn),很明顯可以用上簡(jiǎn)單工廠模式或工廠方法模式。為了簡(jiǎn)單,這里選用簡(jiǎn)單工廠。客戶告訴裝機(jī)工程師自己的選擇,然后裝機(jī)工程師會(huì)通過(guò)相應(yīng)的工廠去獲取相應(yīng)的實(shí)例對(duì)象。

源代碼

CPU接口與具體實(shí)現(xiàn)

1 public interface Cpu {2     public void calculate();3 }
 1 public class IntelCpu implements Cpu { 2     /** 3      * CPU的針腳數(shù) 4      */ 5     PRivate int pins = 0; 6     public  IntelCpu(int pins){ 7         this.pins = pins; 8     } 9     @Override10     public void calculate() {11         // TODO Auto-generated method stub12         System.out.println("Intel CPU的針腳數(shù):" + pins);13     }14 15 }
 1 public class AmdCpu implements Cpu { 2     /** 3      * CPU的針腳數(shù) 4      */ 5     private int pins = 0; 6     public  AmdCpu(int pins){ 7         this.pins = pins; 8     } 9     @Override10     public void calculate() {11         // TODO Auto-generated method stub12         System.out.println("AMD CPU的針腳數(shù):" + pins);13     }14 }

主板接口與具體實(shí)現(xiàn)

1 public interface Mainboard {2     public void installCPU();3 }
 1 public class IntelMainboard implements Mainboard { 2     /** 3      * CPU插槽的孔數(shù) 4      */ 5     private int cpuHoles = 0; 6     /** 7      * 構(gòu)造方法,傳入CPU插槽的孔數(shù) 8      * @param cpuHoles 9      */10     public IntelMainboard(int cpuHoles){11         this.cpuHoles = cpuHoles;12     }13     @Override14     public void installCPU() {15         // TODO Auto-generated method stub16         System.out.println("Intel主板的CPU插槽孔數(shù)是:" + cpuHoles);17     }18 19 }
 1 public class AmdMainboard implements Mainboard { 2     /** 3      * CPU插槽的孔數(shù) 4      */ 5     private int cpuHoles = 0; 6     /** 7      * 構(gòu)造方法,傳入CPU插槽的孔數(shù) 8      * @param cpuHoles 9      */10     public AmdMainboard(int cpuHoles){11         this.cpuHoles = cpuHoles;12     }13     @Override14     public void installCPU() {15         // TODO Auto-generated method stub16         System.out.println("AMD主板的CPU插槽孔數(shù)是:" + cpuHoles);17     }18 }

CPU與主板工廠類

 1 public class CpuFactory { 2     public static Cpu createCpu(int type){ 3         Cpu cpu = null; 4         if(type == 1){ 5             cpu = new IntelCpu(755); 6         }else if(type == 2){ 7             cpu = new AmdCpu(938); 8         } 9         return cpu;10     }11 }
 1 public class MainboardFactory { 2     public static Mainboard createMainboard(int type){ 3         Mainboard mainboard = null; 4         if(type == 1){ 5             mainboard = new IntelMainboard(755); 6         }else if(type == 2){ 7             mainboard = new AmdMainboard(938); 8         } 9         return mainboard;10     }11 }

裝機(jī)工程師類與客戶類運(yùn)行結(jié)果如下:

 1 public class ComputerEngineer { 2     /** 3      * 定義組裝機(jī)需要的CPU 4      */ 5     private Cpu cpu = null; 6     /** 7      * 定義組裝機(jī)需要的主板 8      */ 9     private Mainboard mainboard = null;10     public void makeComputer(int cpuType , int mainboard){11         /**12          * 組裝機(jī)器的基本步驟13          */14         //1:首先準(zhǔn)備好裝機(jī)所需要的配件15         prepareHardwares(cpuType, mainboard);16         //2:組裝機(jī)器17         //3:測(cè)試機(jī)器18         //4:交付客戶19     }20     private void prepareHardwares(int cpuType , int mainboard){21         //這里要去準(zhǔn)備CPU和主板的具體實(shí)現(xiàn),為了示例簡(jiǎn)單,這里只準(zhǔn)備這兩個(gè)22         //可是,裝機(jī)工程師并不知道如何去創(chuàng)建,怎么辦呢?23         24         //直接找相應(yīng)的工廠獲取25         this.cpu = CpuFactory.createCpu(cpuType);26         this.mainboard = MainboardFactory.createMainboard(mainboard);27         28         //測(cè)試配件是否好用29         this.cpu.calculate();30         this.mainboard.installCPU();31     }32 }
1 public class Client {2     public static void main(String[]args){3         ComputerEngineer cf = new ComputerEngineer();4         cf.makeComputer(1,1);5     }6 }

運(yùn)行結(jié)果如下:

上面的實(shí)現(xiàn),雖然通過(guò)簡(jiǎn)單工廠方法解決了:對(duì)于裝機(jī)工程師,只知CPU和主板的接口,而不知道具體實(shí)現(xiàn)的問(wèn)題。但還有一個(gè)問(wèn)題沒有解決,那就是這些CPU對(duì)象和主板對(duì)象其實(shí)是有關(guān)系的,需要相互匹配的。而上面的實(shí)現(xiàn)中,并沒有維護(hù)這種關(guān)聯(lián)關(guān)系,CPU和主板是由客戶任意選擇,這是有問(wèn)題的。比如在客戶端調(diào)用makeComputer時(shí),傳入?yún)?shù)為(1,2),運(yùn)行結(jié)果如下:

觀察上面結(jié)果就會(huì)看出問(wèn)題。客戶選擇的是Intel的CPU針腳數(shù)為755,而選擇的主板是AMD,主板上的CPU插孔是938,根本無(wú)法組裝,這就是沒有維護(hù)配件之間的關(guān)系造成的。該怎么解決這個(gè)問(wèn)題呢?

引進(jìn)抽象工廠模式

  每一個(gè)模式都是針對(duì)一定問(wèn)題的解決方案。抽象工廠模式與工廠方法模式的最大區(qū)別就在于,工廠方法模式針對(duì)的是一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu);而抽象工廠模式則需要面對(duì)多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)。

  在學(xué)習(xí)抽象工廠具體實(shí)例之前,應(yīng)該明白兩個(gè)重要的概念:產(chǎn)品族和產(chǎn)品等級(jí)。

  所謂產(chǎn)品族,是指位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中,功能相關(guān)聯(lián)的產(chǎn)品組成的家族。比如AMD的主板、芯片組、CPU組成一個(gè)家族,Intel的主板、芯片組、CPU組成一個(gè)家族。而這兩個(gè)家族都來(lái)自于三個(gè)產(chǎn)品等級(jí):主板、芯片組、CPU。一個(gè)等級(jí)結(jié)構(gòu)是由相同的結(jié)構(gòu)的產(chǎn)品組成,示意圖如下:

顯然,每一個(gè)產(chǎn)品族中含有產(chǎn)品的數(shù)目,與產(chǎn)品等級(jí)結(jié)構(gòu)的數(shù)目是相等的。產(chǎn)品的等級(jí)結(jié)構(gòu)與產(chǎn)品族將產(chǎn)品按照不同方向劃分,形成一個(gè)二維的坐標(biāo)系。橫軸表示產(chǎn)品的等級(jí)結(jié)構(gòu),縱軸表示產(chǎn)品族,上圖共有兩個(gè)產(chǎn)品族,分布于三個(gè)不同的產(chǎn)品等級(jí)結(jié)構(gòu)中。只要指明一個(gè)產(chǎn)品所處的產(chǎn)品族以及它所屬的等級(jí)結(jié)構(gòu),就可以唯一的確定這個(gè)產(chǎn)品。

上面所給出的三個(gè)不同的等級(jí)結(jié)構(gòu)具有平行的結(jié)構(gòu)。因此,如果采用工廠方法模式,就勢(shì)必要使用三個(gè)獨(dú)立的工廠等級(jí)結(jié)構(gòu)來(lái)對(duì)付這三個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)。由于這三個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)的相似性,會(huì)導(dǎo)致三個(gè)平行的工廠等級(jí)結(jié)構(gòu)。隨著產(chǎn)品等級(jí)結(jié)構(gòu)的數(shù)目的增加,工廠方法模式所給出的工廠等級(jí)結(jié)構(gòu)的數(shù)目也會(huì)隨之增加。如下圖:

那么,是否可以使用同一個(gè)工廠等級(jí)結(jié)構(gòu)來(lái)對(duì)付這些相同或者極為相似的產(chǎn)品等級(jí)結(jié)構(gòu)呢?當(dāng)然可以的,而且這就是抽象工廠模式的好處。同一個(gè)工廠等級(jí)結(jié)構(gòu)負(fù)責(zé)三個(gè)不同產(chǎn)品等級(jí)結(jié)構(gòu)中的產(chǎn)品對(duì)象的創(chuàng)建。

可以看出,一個(gè)工廠等級(jí)結(jié)構(gòu)可以創(chuàng)建出分屬于不同產(chǎn)品等級(jí)結(jié)構(gòu)的一個(gè)產(chǎn)品族中的所有對(duì)象。顯然,這時(shí)候抽象工廠模式比簡(jiǎn)單工廠模式、工廠方法模式更有效率。對(duì)應(yīng)于每一個(gè)產(chǎn)品族都有一個(gè)具體工廠。而每一個(gè)具體工廠負(fù)責(zé)創(chuàng)建屬于同一個(gè)產(chǎn)品族,但是分屬于不同等級(jí)結(jié)構(gòu)的產(chǎn)品。

抽象工廠模式結(jié)構(gòu)

  抽象工廠模式是對(duì)象的創(chuàng)建模式,它是工廠方法模式的進(jìn)一步推廣。

  假設(shè)一個(gè)子系統(tǒng)需要一些產(chǎn)品對(duì)象,而這些產(chǎn)品又屬于一個(gè)以上的產(chǎn)品等級(jí)結(jié)構(gòu)。那么為了將消費(fèi)這些產(chǎn)品對(duì)象的責(zé)任和創(chuàng)建這些產(chǎn)品對(duì)象的責(zé)任分割開來(lái),可以引進(jìn)抽象工廠模式。這樣的話,消費(fèi)產(chǎn)品的一方不需要直接參與產(chǎn)品的創(chuàng)建工作,而只需要向一個(gè)公用的工廠接口請(qǐng)求所需要的產(chǎn)品。

  通過(guò)使用抽象工廠模式,可以處理具有相同(或者相似)等級(jí)結(jié)構(gòu)中的多個(gè)產(chǎn)品族中的產(chǎn)品對(duì)象的創(chuàng)建問(wèn)題。如下圖所示:

由于這兩個(gè)產(chǎn)品族的等級(jí)結(jié)構(gòu)相同,因此使用同一個(gè)工廠族也可以處理這兩個(gè)產(chǎn)品族的創(chuàng)建問(wèn)題,這就是抽象工廠模式。根據(jù)產(chǎn)品角色的結(jié)構(gòu)圖,就不難給出工廠角色的結(jié)構(gòu)設(shè)計(jì)圖。

可以看出,每一個(gè)工廠角色都有兩個(gè)工廠方法,分別負(fù)責(zé)創(chuàng)建分屬不同產(chǎn)品等級(jí)結(jié)構(gòu)的產(chǎn)品對(duì)象。

源代碼

  前面示例實(shí)現(xiàn)的CPU接口和CPU實(shí)現(xiàn)對(duì)象,主板接口和主板實(shí)現(xiàn)對(duì)象,都不需要變化。

  前面示例中創(chuàng)建CPU的簡(jiǎn)單工廠和創(chuàng)建主板的簡(jiǎn)單工廠,都不再需要。

  新加入的抽象工廠類和實(shí)現(xiàn)類:

 1 public interface AbstractFactory { 2     /** 3      * 創(chuàng)建CPU對(duì)象 4      * @return CPU對(duì)象 5      */ 6     public Cpu createCpu(); 7     /** 8      * 創(chuàng)建主板對(duì)象 9      * @return 主板對(duì)象10      */11     public Mainboard createMainboard();12 }
 1 public class IntelFactory implements AbstractFactory { 2  3     @Override 4     public Cpu createCpu() { 5         // TODO Auto-generated method stub 6         return new IntelCpu(755); 7     } 8  9     @Override10     public Mainboard createMainboard() {11         // TODO Auto-generated method stub12         return new IntelMainboard(755);13     }14 15 }
 1 public class AmdFactory implements AbstractFactory { 2  3     @Override 4     public Cpu createCpu() { 5         // TODO Auto-generated method stub 6         return new IntelCpu(938); 7     } 8  9     @Override10     public Mainboard createMainboard() {11         // TODO Auto-generated method stub12         return new IntelMainboard(938);13     }14 15 }

裝機(jī)工程師類跟前面的實(shí)現(xiàn)相比,主要的變化是:從客戶端不再傳入選擇CPU和主板的參數(shù),而是直接傳入客戶已經(jīng)選擇好的產(chǎn)品對(duì)象。這樣就避免了單獨(dú)去選擇CPU和主板所帶來(lái)的兼容性問(wèn)題,客戶要選就是一套,就是一個(gè)系列。

 1 public class ComputerEngineer { 2     /** 3      * 定義組裝機(jī)需要的CPU 4      */ 5     private Cpu cpu = null; 6     /** 7      * 定義組裝機(jī)需要的主板 8      */ 9     private Mainboard mainboard = null;10     public void makeComputer(AbstractFactory af){11         /**12          * 組裝機(jī)器的基本步驟13          */14         //1:首先準(zhǔn)備好裝機(jī)所需要的配件15         prepareHardwares(af);16         //2:組裝機(jī)器17         //3:測(cè)試機(jī)器18         //4:交付客戶19     }20     private void prepareHardwares(AbstractFactory af){21         //這里要去準(zhǔn)備CPU和主板的具體實(shí)現(xiàn),為了示例簡(jiǎn)單,這里只準(zhǔn)備這兩個(gè)22         //可是,裝機(jī)工程師并不知道如何去創(chuàng)建,怎么辦呢?23         24         //直接找相應(yīng)的工廠獲取25         this.cpu = af.createCpu();26         this.mainboard = af.createMainboard();27         28         //測(cè)試配件是否好用29         this.cpu.calculate();30         this.mainboard.installCPU();31     }32 }

客戶端代碼:

 1 public class Client { 2     public static void main(String[]args){ 3         //創(chuàng)建裝機(jī)工程師對(duì)象 4         ComputerEngineer cf = new ComputerEngineer(); 5         //客戶選擇并創(chuàng)建需要使用的產(chǎn)品對(duì)象 6         AbstractFactory af = new IntelFactory(); 7         //告訴裝機(jī)工程師自己選擇的產(chǎn)品,讓裝機(jī)工程師組裝電腦 8         cf.makeComputer(af); 9     }10 }

抽象工廠的功能是為一系列相關(guān)對(duì)象或相互依賴的對(duì)象創(chuàng)建一個(gè)接口。一定要注意,這個(gè)接口內(nèi)的方法不是任意堆砌的,而是一系列相關(guān)或相互依賴的方法。比如上面例子中的主板和CPU,都是為了組裝一臺(tái)電腦的相關(guān)對(duì)象。不同的裝機(jī)方案,代表一種具體的電腦系列。

由于抽象工廠定義的一系列對(duì)象通常是相關(guān)或相互依賴的,這些產(chǎn)品對(duì)象就構(gòu)成了一個(gè)產(chǎn)品族,也就是抽象工廠定義了一個(gè)產(chǎn)品族。

這就帶來(lái)非常大的靈活性,切換產(chǎn)品族的時(shí)候,只要提供不同的抽象工廠實(shí)現(xiàn)就可以了,也就是說(shuō)現(xiàn)在是以一個(gè)產(chǎn)品族作為一個(gè)整體被切換。

在什么情況下應(yīng)當(dāng)使用抽象工廠模式

  1.一個(gè)系統(tǒng)不應(yīng)當(dāng)依賴于產(chǎn)品類實(shí)例如何被創(chuàng)建、組合和表達(dá)的細(xì)節(jié),這對(duì)于所有形態(tài)的工廠模式都是重要的。

  2.這個(gè)系統(tǒng)的產(chǎn)品有多于一個(gè)的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品。

  3.同屬于同一個(gè)產(chǎn)品族的產(chǎn)品是在一起使用的,這一約束必須在系統(tǒng)的設(shè)計(jì)中體現(xiàn)出來(lái)。(比如:Intel主板必須使用Intel CPU、Intel芯片組)

  4.系統(tǒng)提供一個(gè)產(chǎn)品類的庫(kù),所有的產(chǎn)品以同樣的接口出現(xiàn),從而使客戶端不依賴于實(shí)現(xiàn)。

抽象工廠模式的起源

  抽象工廠模式的起源或者最早的應(yīng)用,是用于創(chuàng)建分屬于不同操作系統(tǒng)的視窗構(gòu)建。比如:命令按鍵(Button)與文字框(Text)都是視窗構(gòu)建,在UNIX操作系統(tǒng)的視窗環(huán)境和Windows操作系統(tǒng)的視窗環(huán)境中,這兩個(gè)構(gòu)建有不同的本地實(shí)現(xiàn),它們的細(xì)節(jié)有所不同。

  在每一個(gè)操作系統(tǒng)中,都有一個(gè)視窗構(gòu)建組成的構(gòu)建家族。在這里就是Button和Text組成的產(chǎn)品族。而每一個(gè)視窗構(gòu)件都構(gòu)成自己的等級(jí)結(jié)構(gòu),由一個(gè)抽象角色給出抽象的功能描述,而由具體子類給出不同操作系統(tǒng)下的具體實(shí)現(xiàn)。

可以發(fā)現(xiàn)在上面的產(chǎn)品類圖中,有兩個(gè)產(chǎn)品的等級(jí)結(jié)構(gòu),分別是Button等級(jí)結(jié)構(gòu)和Text等級(jí)結(jié)構(gòu)。同時(shí)有兩個(gè)產(chǎn)品族,也就是UNIX產(chǎn)品族和Windows產(chǎn)品族。UNIX產(chǎn)品族由UNIX Button和UNIX Text產(chǎn)品構(gòu)成;而Windows產(chǎn)品族由Windows Button和Windows Text產(chǎn)品構(gòu)成。

系統(tǒng)對(duì)產(chǎn)品對(duì)象的創(chuàng)建需求由一個(gè)工程的等級(jí)結(jié)構(gòu)滿足,其中有兩個(gè)具體工程角色,即UnixFactory和WindowsFactory。UnixFactory對(duì)象負(fù)責(zé)創(chuàng)建Unix產(chǎn)品族中的產(chǎn)品,而WindowsFactory對(duì)象負(fù)責(zé)創(chuàng)建Windows產(chǎn)品族中的產(chǎn)品。這就是抽象工廠模式的應(yīng)用,抽象工廠模式的解決方案如下圖:

顯然,一個(gè)系統(tǒng)只能夠在某一個(gè)操作系統(tǒng)的視窗環(huán)境下運(yùn)行,而不能同時(shí)在不同的操作系統(tǒng)上運(yùn)行。所以,系統(tǒng)實(shí)際上只能消費(fèi)屬于同一個(gè)產(chǎn)品族的產(chǎn)品。

  在現(xiàn)代的應(yīng)用中,抽象工廠模式的使用范圍已經(jīng)大大擴(kuò)大了,不再要求系統(tǒng)只能消費(fèi)某一個(gè)產(chǎn)品族了。因此,可以不必理會(huì)前面所提到的原始用意。

抽象工廠模式的優(yōu)點(diǎn)
  • 分離接口和實(shí)現(xiàn)

  客戶端使用抽象工廠來(lái)創(chuàng)建需要的對(duì)象,而客戶端根本就不知道具體的實(shí)現(xiàn)是誰(shuí),客戶端只是面向產(chǎn)品的接口編程而已。也就是說(shuō),客戶端從具體的產(chǎn)品實(shí)現(xiàn)中解耦。

  • 使切換產(chǎn)品族變得容易

  因?yàn)橐粋€(gè)具體的工廠實(shí)現(xiàn)代表的是一個(gè)產(chǎn)品族,比如上面例子的從Intel系列到AMD系列只需要切換一下具體工廠。

抽象工廠模式的缺點(diǎn)
  • 不太容易擴(kuò)展新的產(chǎn)品

  如果需要給整個(gè)產(chǎn)品族添加一個(gè)新的產(chǎn)品,那么就需要修改抽象工廠,這樣就會(huì)導(dǎo)致修改所有的工廠實(shí)現(xiàn)類。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 甘谷县| 原平市| 宜兰县| 洛扎县| 青铜峡市| 陵川县| 武安市| 伽师县| 昌黎县| 浦县| 宜丰县| 湖北省| 光泽县| 婺源县| 宁阳县| 大名县| 杨浦区| 元江| 河南省| 科技| 海宁市| 连平县| 满城县| 涟水县| 瑞昌市| 宣城市| 金寨县| 广德县| 呼伦贝尔市| 郧西县| 浦北县| 和平区| 新竹市| 阆中市| 南安市| 建湖县| 荣成市| 平原县| 海兴县| 巩留县| 安庆市|