<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          設(shè)計(jì)模式之工廠模式

          共 17999字,需瀏覽 36分鐘

           ·

          2021-03-26 14:11

          一、工廠模式簡(jiǎn)介

          1、使用工廠模式的好處

          工廠模式是創(chuàng)建型模式中最典型的模式,主要作用是用來(lái)創(chuàng)建對(duì)象,使用工廠模式替代new操作有如下幾個(gè)好處:
          1:解耦,把創(chuàng)建對(duì)象的工作和使用對(duì)象的工作分開(kāi),比如我們想使用對(duì)象A,我們無(wú)需關(guān)心對(duì)象A是如何創(chuàng)建的,直接去工廠獲取就行。
          2:對(duì)于構(gòu)造函數(shù)很復(fù)雜的對(duì)象,可以很好地對(duì)外層屏蔽代碼的復(fù)雜性
          3:把初始化實(shí)例的工作放到工廠里進(jìn)行統(tǒng)一管理,使代碼更容易維護(hù)
          4:修改代碼時(shí)不會(huì)引起太大的變動(dòng),如果想改代碼的話,只需要改一處即可,良好的擴(kuò)展性
          5:減少代碼量,如果構(gòu)造方法比較復(fù)雜,有很多很多個(gè)構(gòu)造函數(shù),需要一連串的代碼創(chuàng)建對(duì)象,如果使用new就會(huì)造成很多重復(fù)的代碼。

          2、用一個(gè)例子說(shuō)明使用工廠模式相對(duì)于new操作的優(yōu)勢(shì)

          下面我們分別從使用new創(chuàng)建對(duì)象和工廠模式兩種方面講解,幫助大家理解工廠模式的優(yōu)勢(shì)。

          需求1:有三個(gè)用戶,需要定制相同的藍(lán)莓黑巧動(dòng)物奶油做的蛋糕。使用new創(chuàng)建對(duì)象:

          // 蛋糕類
          public class Cake {
              private String fruit;// 配料:水果
              private String chocolate;// 配料:巧克力
              private String cream;// 配料:奶油

              public Cake(String fruit, String chocolate, String cream){
                  this.fruit = fruit;
                  this.chocolate = chocolate;
                  this.cream = cream;
              }
          }
          public class Test1 {
              public static void main(String[] args) {
                  // 用戶A訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油做的蛋糕
                  Cake cake1 = new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油");
                  // 用戶B訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油做的蛋糕
                  Cake cake2 = new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油");
                  // 用戶C訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油做的蛋糕
                  Cake cake3 = new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油");
              }
          }

          工廠模式:

          // 蛋糕工廠
          public class CakeFactory {
              public Cake createCake(){
                  return new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油");
              }
          }
          public class Test2 {
              public static void main(String[] args) {
                  CakeFactory cakeFactory = new CakeFactory();
                  // 用戶A訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油做的蛋糕
                  cakeFactory.createCake();
                  // 用戶B訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油做的蛋糕
                  cakeFactory.createCake();
                  // 用戶C訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油做的蛋糕
                  cakeFactory.createCake();
              }
          }

          需求2;這三個(gè)用戶想要在蛋糕中加入一種堅(jiān)果,如果使用new創(chuàng)建對(duì)象,需要修改三個(gè)new操作,使用工廠模式,只需修改工廠中的new操作即可,改動(dòng)更少,帶來(lái)錯(cuò)誤的可能性就越少。 使用new創(chuàng)建對(duì)象:

          // 蛋糕類
          public class Cake {
              private String fruit;// 配料:水果
              private String chocolate;// 配料:巧克力
              private String cream;// 配料:奶油
              private String nut;// 配料:堅(jiān)果

              public Cake(String fruit, String chocolate, String cream, String nut){
                  this.fruit = fruit;
                  this.chocolate = chocolate;
                  this.cream = cream;
                  this.nut = nut;
              }
          }
          public class Test1 {
              public static void main(String[] args) {
                  // 用戶A訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油榛子做的蛋糕
                  Cake cake1 = new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油""榛子");
                  // 用戶B訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油榛子做的蛋糕
                  Cake cake2 = new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油""榛子");
                  // 用戶C訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油榛子做的蛋糕
                  Cake cake3 = new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油""榛子");
              }
          }

          工廠模式:

          // 蛋糕工廠
          public class CakeFactory {
              public Cake createCake(){
                  return new Cake("藍(lán)莓""黑巧克力""動(dòng)物奶油""榛子");
              }
          }
          public class Test2 {
              public static void main(String[] args) {
                  CakeFactory cakeFactory = new CakeFactory();
                  // 用戶A訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油榛子做的蛋糕
                  cakeFactory.createCake();
                  // 用戶B訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油榛子做的蛋糕
                  cakeFactory.createCake();
                  // 用戶C訂了一個(gè)藍(lán)莓黑巧動(dòng)物奶油榛子做的蛋糕
                  cakeFactory.createCake();
              }
          }
          3、工廠模式分類

          工廠模式,包含三種情況,簡(jiǎn)單工廠工廠方法抽象工廠,下面我們就來(lái)一一介紹一下。

          我相信大家都有這樣的困惑,目前我所在的項(xiàng)目都在程序開(kāi)發(fā)的過(guò)程中,還是有很多的new()操作出現(xiàn)在程序中,并沒(méi)有通過(guò)工廠來(lái)創(chuàng)建對(duì)象,一方面可能是因?yàn)槲覀冏陨肀容^懶,不規(guī)范項(xiàng)目的編碼形式,另外一方面也是由于項(xiàng)目的進(jìn)度比較緊,沒(méi)有那么多的時(shí)間去完成工廠的統(tǒng)一創(chuàng)建。

          二、簡(jiǎn)單工廠

          我們將用幾個(gè)例子來(lái)逐步講解簡(jiǎn)單工廠、工廠方法、抽象工廠,下面我們就開(kāi)始吧。

          1、簡(jiǎn)單工廠示例

          小明在老家開(kāi)了一家飲品店,提供多種飲品,當(dāng)有顧客來(lái)店里,只需要和服務(wù)員說(shuō)他想喝哪種飲料,服務(wù)員便可提供哪種飲料,這就是簡(jiǎn)單工廠模式,服務(wù)員就是這個(gè)簡(jiǎn)單工廠。

          // 抽象飲料
          public abstract class Drink {
              public abstract void desc();
          }

          // 蘋(píng)果汁
          public class AppleDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯蘋(píng)果汁!");
              }
          }

          // 葡萄汁
          public class GrapeDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯葡萄汁!");
              }
          }

          // 西瓜汁
          public class WatermelonDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯西瓜汁!");
              }
          }

          // 飲料工廠
          public class DrinkFactory {
              // name:飲料名字
              public Drink getDrink(String name){
                  if("apple".equals(name)){
                      return new AppleDrink();
                  }else if("watermelon".equals(name)){
                      return new WatermelonDrink();
                  }else if("grape".equals(name)){
                      return new GrapeDrink();
                  }
                  return null;
              }
          }

          // 客戶端
          public class Client {
              public static void main(String[] args) {
                  DrinkFactory drinkFactory = new DrinkFactory();
                  // 顧客想要蘋(píng)果汁
                  Drink appleDrink = drinkFactory.getDrink("apple");
                  appleDrink.desc();

                  // 顧客想要葡萄汁
                  Drink grapeDrink = drinkFactory.getDrink("grape");
                  grapeDrink.desc();
              }
          }
          2、簡(jiǎn)單工廠的適用場(chǎng)景

          (1)、工廠類負(fù)責(zé)創(chuàng)建的對(duì)象比較少。
          (2)、客戶端(應(yīng)用層)只知道傳入工廠類的參數(shù),對(duì)于如何創(chuàng)建對(duì)象(邏輯)不關(guān)心。

          3、簡(jiǎn)單工廠的優(yōu)點(diǎn)

          只需要傳入一個(gè)正確的參數(shù),就可以獲取你所需要的對(duì)象,而無(wú)需知道其創(chuàng)建細(xì)節(jié),工廠類要有必要的判斷邏輯(if else),可以決定在什么時(shí)候創(chuàng)建哪一個(gè)產(chǎn)品的實(shí)例,客戶端可以免除直接創(chuàng)建對(duì)象的責(zé)任。

          4、簡(jiǎn)單工廠的缺點(diǎn)

          (1)、工廠類的職責(zé)相對(duì)較重,增加新的產(chǎn)品,需要修改工廠類的判斷邏輯(增加if else分支),修改就意味著引入風(fēng)險(xiǎn),這違反了開(kāi)閉原則
          (2)、當(dāng)產(chǎn)品很多的時(shí)候,這個(gè)工廠類就會(huì)很復(fù)雜,不利于維護(hù)和擴(kuò)展,代碼無(wú)法閱讀,很難交接。
          (3)、無(wú)法形成基于繼承的等級(jí)結(jié)構(gòu)。在工廠方法和抽象工廠中,會(huì)講到產(chǎn)品族和產(chǎn)品等級(jí)結(jié)構(gòu),再了解什么是基于繼承的等級(jí)結(jié)構(gòu)。

          三、工廠方法

          1、工廠方法示例

          后來(lái)店里飲料品種越來(lái)越多,每增加一款飲料都需要讓服務(wù)員知曉,否則顧客說(shuō)的時(shí)候,服務(wù)員就無(wú)法提供(這就是簡(jiǎn)單工廠中所說(shuō)的對(duì)工廠類的修改)。

          于是,小明直接買(mǎi)了飲料機(jī),每種飲料都有自己的飲料機(jī)(這個(gè)飲料機(jī)就是工廠方法中的產(chǎn)品工廠,每個(gè)產(chǎn)品都有自己的工廠),顧客想喝什么,就自己去飲料機(jī)取,飲品店以后想增加飲料,只要增加飲料機(jī)即可(工廠方法相對(duì)于簡(jiǎn)單工廠,更加易于擴(kuò)展)。

          // 抽象飲料
          public abstract class Drink {
              public abstract void desc();
          }

          // 蘋(píng)果汁
          public class AppleDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯蘋(píng)果汁!");
              }
          }

          // 葡萄汁
          public class GrapeDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯葡萄汁!");
              }
          }

          // 西瓜汁
          public class WatermelonDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯西瓜汁!");
              }
          }

          // 抽象飲料工廠
          public abstract class DrinkFactory {
              public abstract Drink getDrink();
          }

          // 蘋(píng)果汁飲料工廠(蘋(píng)果汁飲料機(jī))
          public class AppleDrinkFactory extends DrinkFactory {
              @Override
              public Drink getDrink() {
                  return new AppleDrink();
              }
          }

          // 葡萄汁飲料工廠
          public class GrapeDrinkFactory extends DrinkFactory {
              @Override
              public Drink getDrink() {
                  return new GrapeDrink();
              }
          }

          // 西瓜汁飲料工廠
          public class WatermelonDrinkFactory extends DrinkFactory {
              @Override
              public Drink getDrink() {
                  return new WatermelonDrink();
              }
          }

          // 客戶端
          public class Client {
              public static void main(String[] args) {
                  // 顧客想要蘋(píng)果汁
                  DrinkFactory appleDrinkFactory = new AppleDrinkFactory();
                  Drink appleDrink = appDrinkFactory.getDrink();
                  appleDrink.desc();

                  // 顧客想要葡萄汁
                  DrinkFactory grapeDrinkFactory = new GrapeDrinkFactory();
                  Drink grapeDrink = grapeDrinkFactory.getDrink();
                  grapeDrink.desc();
              }
          }
          2、工廠方法和簡(jiǎn)單工廠的區(qū)別

          簡(jiǎn)單工廠:所有的產(chǎn)品都在一個(gè)工廠中生產(chǎn),在工廠中使用if else根據(jù)傳入?yún)?shù)判斷生產(chǎn)哪種產(chǎn)品,當(dāng)增加一種產(chǎn)品的時(shí)候,就需要修改工廠的if else邏輯。

          工廠方法:每種產(chǎn)品都有自己的工廠,當(dāng)需要增加一種產(chǎn)品時(shí),無(wú)需修改現(xiàn)有的工廠,只需要增加一種工廠即可。遵循了開(kāi)閉原則,對(duì)于擴(kuò)展是開(kāi)放的,對(duì)于修改是關(guān)閉的。

          3、工廠方法的優(yōu)點(diǎn)

          (1)、用戶只需要關(guān)心所需產(chǎn)品對(duì)應(yīng)的工廠,無(wú)需關(guān)心產(chǎn)品的創(chuàng)建細(xì)節(jié)。
          (2)、加入新產(chǎn)品時(shí),只需要再增加對(duì)應(yīng)的工廠,而不用修改已有的工廠,符合開(kāi)閉原則,提高擴(kuò)展性。

          4、工廠方法的缺點(diǎn)

          類爆炸,因?yàn)槊總€(gè)產(chǎn)品都要有一個(gè)工廠,如果產(chǎn)品很多,那就會(huì)有很多的工廠。用上面的例子來(lái)描述,如果后續(xù)飲品店出了成百上千種飲品,就要在店里放成百上千臺(tái)飲料機(jī),店里放不下啊。。。

          四、抽象工廠

          1、抽象工廠示例

          至于抽象工廠模式,可以用套餐來(lái)理解。小明在后期,除了提供飲品,還給每種飲品搭配了合適的甜點(diǎn),向顧客提供下午茶套餐,以此來(lái)提高銷(xiāo)售量。

          所以飲品店制定了一套標(biāo)準(zhǔn)(抽象工廠,具體工廠需要遵循的工廠接口),所有的套餐(具體工廠)必須遵循該標(biāo)準(zhǔn),比如這個(gè)抽象標(biāo)準(zhǔn)可能是:1、需要有一杯果汁。2、需要有一塊甜點(diǎn)。于是有了第一個(gè)套餐(具體工廠):西瓜汁 + 泡芙,我們稱之為套餐A,那顧客點(diǎn)套餐A,即可獲得剛才所說(shuō)產(chǎn)品。當(dāng)然這里面的西瓜汁、泡芙(具體產(chǎn)品對(duì)象),也需要遵守相應(yīng)的產(chǎn)品規(guī)則(產(chǎn)品接口),以保證顧客能吃到放心食品。

          產(chǎn)品接口如下:

          // 飲料抽象類
          public abstract class Drink {
              public abstract void desc();
          }

          // 甜點(diǎn)抽象類
          public abstract class Dessert {
              public abstract void desc();
          }

          具體產(chǎn)品對(duì)象如下:

          // 蘋(píng)果汁
          public class AppleDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯蘋(píng)果汁!");
              }
          }

          // 葡萄汁
          public class GrapeDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯葡萄汁!");
              }
          }

          // 西瓜汁
          public class WatermelonDrink extends Drink {
              @Override
              public void desc() {
                  System.out.println("這是一杯西瓜汁!");
              }
          }

          // 泡芙
          public class Puff extends Dessert {
              @Override
              public void desc() {
                  System.out.println("這是一塊泡芙!");
              }
          }

          // 慕斯蛋糕
          public class MousseCake extends Dessert {
              @Override
              public void desc() {
                  System.out.println("這是一塊慕斯蛋糕!");
              }
          }

          // 提拉米蘇蛋糕
          public class Tiramisu extends Dessert {
              @Override
              public void desc() {
                  System.out.println("這是一塊提拉米蘇蛋糕!");
              }
          }

          抽象工廠如下:

          // 下午茶套餐工廠
          public interface SetFactory {
              Drink getDrink();
              Dessert getDessert();
          }

          具體工廠如下:

          /**
           * 套餐A的工廠
           * 套餐A提供西瓜汁 + 泡芙
           */

          public class ASetFactory implements SetFactory {
              @Override
              public Drink getDrink() {
                  return new WatermelonDrink();
              }

              @Override
              public Dessert getDessert() {
                  return new Puff();
              }
          }

          /**
           * 套餐B的工廠
           * 套餐B提供葡萄汁 + 慕斯蛋糕
           */

          public class BSetFactory implements SetFactory {

              @Override
              public Drink getDrink() {
                  return new GrapeDrink();
              }

              @Override
              public Dessert getDessert() {
                  return new MousseCake();
              }
          }

          /**
           * 套餐C的工廠
           * 套餐C提供蘋(píng)果汁 + 提拉米蘇蛋糕
           */

          public class CSetFactory implements SetFactory {
              @Override
              public Drink getDrink() {
                  return new AppleDrink();
              }

              @Override
              public Dessert getDessert() {
                  return new Tiramisu();
              }
          }

          客戶端如下:

          public class Client {
              public static void main(String[] args) {
                  // 顧客想要一份A套餐
                  System.out.println("------A套餐-------");
                  SetFactory aSetFactory = new ASetFactory();
                  Drink aDrink = aSetFactory.getDrink();
                  Dessert aDessert = aSetFactory.getDessert();
                  aDrink.desc();
                  aDessert.desc();

                  // 顧客想要一份B套餐
                  System.out.println("------B套餐-------");
                  SetFactory bSetFactory = new BSetFactory();
                  Drink bDrink = bSetFactory.getDrink();
                  Dessert bDessert = bSetFactory.getDessert();
                  bDrink.desc();
                  bDessert.desc();
              }
          }

          在這里我們看到,對(duì)于抽象工廠是無(wú)需指定具體的果汁和甜點(diǎn),但是這些果汁、甜點(diǎn)卻是相互依賴的,這也是抽象工廠的意圖:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無(wú)需指定它們具體的類

          3、抽象工廠的優(yōu)點(diǎn)

          將一系列的產(chǎn)品統(tǒng)一到一起創(chuàng)建。

          4、抽象工廠的缺點(diǎn)

          (1)、規(guī)定了所有可能被創(chuàng)建的產(chǎn)品集合,當(dāng)產(chǎn)品集合中需要擴(kuò)展新的產(chǎn)品時(shí),需要修改抽象工廠的接口,違反了開(kāi)閉原則,比如上面的例子,當(dāng)我們需要在套餐中加入一份小吃時(shí),就需要修改抽象工廠和所有的具體工廠,改動(dòng)很大。
          (2)、增加了系統(tǒng)的抽象性和理解難度。

          5、適用場(chǎng)景

          強(qiáng)調(diào)一系列相關(guān)的產(chǎn)品組成一個(gè)產(chǎn)品集合一起使用時(shí),此時(shí)使用抽象工廠模式。

          五:工廠模式總結(jié)

          我們結(jié)合上面飲品店的例子,來(lái)總結(jié)一下簡(jiǎn)單工廠、工廠方法、抽象工廠這三種工廠有什么不同吧,方便大家更好地記憶。

          簡(jiǎn)單工廠,就是所有的產(chǎn)品都在這個(gè)工廠中生產(chǎn),用戶需要告訴工廠他需要哪個(gè)產(chǎn)品,工廠才能給他對(duì)應(yīng)的產(chǎn)品。

          簡(jiǎn)單工廠

          工廠方法,就是每種產(chǎn)品都有自己的工廠,用戶想要哪個(gè)產(chǎn)品,直接去對(duì)應(yīng)的工廠取即可。

          工廠方法

          抽象工廠,相當(dāng)于對(duì)所有的產(chǎn)品進(jìn)行分類(分類的維度根據(jù)業(yè)務(wù)場(chǎng)景來(lái)決定),同一種類的產(chǎn)品在同一工廠生產(chǎn),用戶想要哪一種類的產(chǎn)品,直接去對(duì)應(yīng)的工廠取即可。

          抽象工廠

          標(biāo)注:圖中綠色方框表示工廠,橘色方框表示產(chǎn)品。


          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  逼视频欧美 | 午夜在线成人视频 | 亚洲国产色婷婷 | 高清无码麻豆 | 日本www在线中文字幕 |