乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      創(chuàng)建型設(shè)計(jì)模式--工廠模式、抽象工廠模式

       python_lover 2021-08-06

      一、小案例分析

      1、功能需求:

        實(shí)現(xiàn)一個(gè)發(fā)送信息的功能,要便于擴(kuò)展與維護(hù)。
      (1)發(fā)送信息的工具有很多,比如短信、微信、郵件、QQ等。
      (2)選擇某個(gè)工具進(jìn)行信息發(fā)送。

      2、小菜雞去實(shí)現(xiàn):

      (1)定義一個(gè)發(fā)送工具的父類(接口),并將各種發(fā)送工具作為子類(實(shí)現(xiàn)類)。
      (2)定義一個(gè)選擇發(fā)送工具的類,用于調(diào)用發(fā)送工具(直接new個(gè)子類對(duì)象)。
      (3)代碼實(shí)現(xiàn):

      package creative.pattern.factory.noFactory;
      
      import java.util.Scanner;
      
      /**
       * 測(cè)試類
       *
       */
      public class Demo {
          public static void main(String[] args) {
              new SendMessage();// 實(shí)例化一個(gè)選擇發(fā)送工具的類
          }
      }
      
      /**
       * 定義一個(gè)發(fā)送工具的接口
       *
       */
      interface Sender {
          void sendMessage();
      }
      
      /**
       * 定義一個(gè)短信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class ShortMessageSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送短信");
          }
      }
      
      /**
       * 定義一個(gè)微信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class WeChatSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送微信");
          }
      }
      
      /**
       * 定義一個(gè)郵件發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class MailSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送郵件");
          }
      }
      
      /**
       * 定義一個(gè)選擇發(fā)送工具的類
       */
      class SendMessage {
          /**
           * 用于獲取需要發(fā)送信息工具
           */
          public Sender getSenderType() {
              System.out.println("輸入發(fā)送工具的類型(1-3):");
              System.out.println("1:短信");
              System.out.println("2:微信");
              System.out.println("3:郵件");
              Scanner scanner = new Scanner(System.in);
              String senderType = scanner.nextLine();
              if ("1".equals(senderType)) {
                  return new ShortMessageSender();
              } else if ("2".equals(senderType)) {
                  return new WeChatSender();
              } else if ("3".equals(senderType)) {
                  return new MailSender();
              } else {
                  return null;
              }
          }
      
          public SendMessage() {
              do {
                  Sender sender = getSenderType();// 選擇發(fā)送信息的工具
                  if (sender == null) {
                      System.out.println("歡迎下次使用");
                      break;
                  } else {
                      sender.sendMessage();
                  }
              } while (true);
          }
      }

      (4)代碼分析:
        對(duì)于邏輯簡(jiǎn)單的代碼,這樣實(shí)現(xiàn)沒(méi)有問(wèn)題,但是邏輯稍微復(fù)雜一些且需要修改擴(kuò)展某個(gè)地方時(shí),需要改動(dòng)很多地方。
        比如:再增加一個(gè) QQSender,其需要實(shí)現(xiàn)Sender接口,并重寫相關(guān)方法,然后需要在 SendMessage 類中 去修改相關(guān)代碼,這里違反了開閉原則。若需要增加幾個(gè)SendMessage 類,比如SendMessage2、SendMessage3時(shí),同樣需要改動(dòng)很多代碼。
      (5)UML圖:

       

      二、簡(jiǎn)單工廠模式(SimpleFactory)

      1、什么是簡(jiǎn)單工廠模式:

        簡(jiǎn)單工廠模式屬于創(chuàng)建型模式,不屬于常見的23種常見模式。簡(jiǎn)單的講 簡(jiǎn)單工廠模式是由一個(gè)工廠對(duì)象決定創(chuàng)建出哪一類產(chǎn)品的實(shí)例。

      2、使用:

      (1)簡(jiǎn)單工廠模式,定義了一個(gè)創(chuàng)建對(duì)象的類,然后由這個(gè)類來(lái)封裝實(shí)例化對(duì)象的操作。
      (2)當(dāng)需要大量創(chuàng)建某種類或者對(duì)象時(shí),可以使用工廠模式。

      3、使用簡(jiǎn)單工廠模式實(shí)現(xiàn):

      (1)定義一個(gè)發(fā)送工具的父類(接口),并將各種發(fā)送工具作為子類(實(shí)現(xiàn)類)。
      (2)定義一個(gè)工廠類,用于調(diào)用發(fā)送工具。
      (2)定義一個(gè)選擇發(fā)送工具的類,用于調(diào)用工廠類。
      (3)代碼實(shí)現(xiàn):

      package creative.pattern.factory.simpleFactory;
      
      import java.util.Scanner;
      
      /**
       * 測(cè)試類
       *
       */
      public class SimpleFactoryDemo {
          public static void main(String[] args) {
              new SendMessage();
          }
      }
      
      /**
       * 定義一個(gè)發(fā)送工具的接口
       *
       */
      interface Sender {
          void sendMessage();
      }
      
      /**
       * 定義一個(gè)短信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class ShortMessageSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送短信");
          }
      }
      
      /**
       * 定義一個(gè)微信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class WeChatSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送微信");
          }
      }
      
      /**
       * 定義一個(gè)郵件發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class MailSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送郵件");
          }
      }
      
      /**
       * 使用簡(jiǎn)單工廠模式,管理需要生產(chǎn)的對(duì)象
       *
       */
      class SimpleFactory {
          /**
           * 用于獲取需要發(fā)送信息工具
           */
          public static Sender createSender() {
              System.out.println("輸入發(fā)送工具的類型(1-3):");
              System.out.println("1:短信");
              System.out.println("2:微信");
              System.out.println("3:郵件");
              Scanner scanner = new Scanner(System.in);
              String senderType = scanner.nextLine();
              if ("1".equals(senderType)) {
                  return new ShortMessageSender();
              } else if ("2".equals(senderType)) {
                  return new WeChatSender();
              } else if ("3".equals(senderType)) {
                  return new MailSender();
              } else {
                  return null;
              }
          }
      }
      
      /**
       * 定義一個(gè)選擇發(fā)送工具的類
       */
      class SendMessage {
          public SendMessage() {
              do {
                  Sender sender = SimpleFactory.createSender();// 選擇發(fā)送信息的工具
                  if (sender == null) {
                      System.out.println("歡迎下次使用");
                      break;
                  } else {
                      sender.sendMessage();
                  }
              } while (true);
          }
      }

      (4)代碼分析:
        對(duì)于上述代碼,SendMessage 只與工廠類SimpleFactory 相關(guān)聯(lián),此時(shí)需要擴(kuò)展代碼時(shí),比如擴(kuò)展QQSender,讓其實(shí)現(xiàn)Sender并重寫方法后,在SimpleFactory 中改變相關(guān)代碼即可(違反開閉原則),不需要再改動(dòng)SendMessage 的代碼。
      (5)UML圖:

       

      4、使用靜態(tài)工廠模式實(shí)現(xiàn)(常用形式):

        將上例的SimpleFactory 中public Sender createSender()改為 public static Sender createSender()。
        調(diào)用時(shí),直接使用SimpleFactory.createSender() 即可。

       public static Sender createSender() {
              System.out.println("輸入發(fā)送工具的類型(1-3):");
              System.out.println("1:短信");
              System.out.println("2:微信");
              System.out.println("3:郵件");
              Scanner scanner = new Scanner(System.in);
              String senderType = scanner.nextLine();
              if ("1".equals(senderType)) {
                  return new ShortMessageSender();
              } else if ("2".equals(senderType)) {
                  return new WeChatSender();
              } else if ("3".equals(senderType)) {
                  return new MailSender();
              } else {
                  return null;
              }
          } 

      三、工廠方法模式

      1、什么是工廠方法模式:

        在工廠內(nèi)部定義一個(gè)創(chuàng)建對(duì)象的抽象方法,由子類去確定要實(shí)例化的對(duì)象。簡(jiǎn)單的講 工廠方法模式將對(duì)象實(shí)例化的操作推遲到子類去實(shí)現(xiàn)??梢钥醋龀橄蠊S模式的一個(gè)常見類型。

      2、使用工廠模式實(shí)現(xiàn):

      (1)定義一個(gè)發(fā)送工具的父類(接口),并將各種發(fā)送工具作為子類(實(shí)現(xiàn)類)。
      (2)定義一個(gè)工廠方法接口,并通過(guò)工廠實(shí)現(xiàn)類去實(shí)例化對(duì)象。
      (3)定義一個(gè)選擇發(fā)送工具的類,用于調(diào)用工廠實(shí)現(xiàn)類。
      (4)代碼實(shí)現(xiàn):

      package creative.pattern.factory.factoryMethod;
      
      import java.util.Scanner;
      
      /**
       * 工廠方法模式測(cè)試類
       *
       */
      public class factoryMethodDemo {
          public static void main(String[] args) {
              new SendMessage();
          }
      }
      
      /**
       * 定義一個(gè)發(fā)送工具的接口
       *
       */
      interface Sender {
          void sendMessage();
      }
      
      /**
       * 定義一個(gè)短信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class ShortMessageSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送短信");
          }
      }
      
      /**
       * 定義一個(gè)微信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class WeChatSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送微信");
          }
      }
      
      /**
       * 定義一個(gè)郵件發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class MailSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("發(fā)送郵件");
          }
      }
      
      /**
       * 使用工廠方法模式,讓子類去創(chuàng)建對(duì)象
       *
       */
      interface FactoryMethod {
          Sender sendMessage();
      }
      
      /**
       * 短信工廠類,實(shí)現(xiàn)工廠方法類并重寫相關(guān)方法
       *
       */
      class ShortMessageFactory implements FactoryMethod {
      
          @Override
          public Sender sendMessage() {
              return new ShortMessageSender();
          }
      }
      
      /**
       * 微信工廠類,實(shí)現(xiàn)工廠方法類并重寫相關(guān)方法
       *
       */
      class WeChatFactory implements FactoryMethod {
      
          @Override
          public Sender sendMessage() {
              return new WeChatSender();
          }
      }
      
      /**
       * 郵件工廠類,實(shí)現(xiàn)工廠方法類并重寫相關(guān)方法
       *
       */
      class MailFactory implements FactoryMethod {
      
          @Override
          public Sender sendMessage() {
              return new MailSender();
          }
      }
      
      /**
       * 定義一個(gè)選擇發(fā)送工具的類
       */
      class SendMessage {
          public SendMessage() {
              do {
                  System.out.println("輸入發(fā)送工具的類型(1-3):");
                  System.out.println("1:短信");
                  System.out.println("2:微信");
                  System.out.println("3:郵件");
                  Scanner scanner = new Scanner(System.in);
                  String senderType = scanner.nextLine();
                  if ("1".equals(senderType)) {
                      FactoryMethod factoryMethod = new ShortMessageFactory();
                      Sender sender = factoryMethod.sendMessage();// 選擇發(fā)送短信
                      sender.sendMessage();
                  } else if ("2".equals(senderType)) {
                      FactoryMethod factoryMethod = new WeChatFactory();
                      Sender sender = factoryMethod.sendMessage();// 選擇發(fā)送微信
                      sender.sendMessage();
                  } else if ("3".equals(senderType)) {
                      FactoryMethod factoryMethod = new MailFactory();
                      Sender sender = factoryMethod.sendMessage();// 選擇發(fā)送郵件
                      sender.sendMessage();
                  } else {
                      System.out.println("歡迎下次使用");
                      break;
                  }
              } while (true);
          }
      }

      (5)代碼分析:
        SendMessage 類只與FactoryMethod 有關(guān),當(dāng)擴(kuò)展新的功能時(shí),比如QQSender,只需創(chuàng)建一個(gè)QQFactory,實(shí)現(xiàn)FactoryMethod 并重寫其方法即可,調(diào)用時(shí)無(wú)需更改其他代碼(必要的邏輯處理除外,符合開閉原則)。
      (6)UML圖:

       

      四、抽象工廠模式

      1、什么是抽象工廠模式

        為創(chuàng)建一組相關(guān)或相互依賴的對(duì)象提供一個(gè)接口,而且無(wú)需指定他們的具體類。
      注:
        產(chǎn)品族:是指位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中功能相關(guān)聯(lián)的產(chǎn)品組成的家族。
        產(chǎn)品等級(jí)結(jié)構(gòu):可以理解為一個(gè)接口或者一個(gè)抽象類。

      2、抽象工廠模式與工廠方法模式的區(qū)別

      (1)抽象工廠模式是工廠方法模式的升級(jí)版,其針對(duì)的是多個(gè)產(chǎn)品等級(jí)結(jié)構(gòu),即抽象工廠模式所提供的產(chǎn)品是衍生自不同的接口或抽象類。
      (2)工廠方法模式:針對(duì)一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu),即工廠方法模式衍生自同一個(gè)接口或者抽象類。
      (3)如下圖所示,ShortMessage 與 WeChat屬于同一個(gè)產(chǎn)品等級(jí),ShortMessage 與 ShortMessage2屬于兩個(gè)產(chǎn)品等級(jí),為產(chǎn)品族。所以若存在兩個(gè)產(chǎn)品等級(jí)及以上的情況,即為抽象工廠模式,若是同一個(gè)產(chǎn)品等級(jí),則為工廠方法模式。
        下圖為工廠方法模式:

      下圖為抽象工廠模式:

      3、舉例:

        在之前案例的基礎(chǔ)上,增加一個(gè)功能,微信、短信均可以圖片。
      (1)定義一個(gè)發(fā)送工具的父類(接口),并將各種發(fā)送工具作為子類(實(shí)現(xiàn)類)。
      (2)定義一個(gè)工廠方法接口,在方法中對(duì)產(chǎn)品族進(jìn)行約束,并通過(guò)工廠實(shí)現(xiàn)類去實(shí)例化對(duì)象。
      (3)定義一個(gè)選擇發(fā)送工具的類(測(cè)試類),用于調(diào)用工廠實(shí)現(xiàn)類。
      (4)代碼實(shí)現(xiàn):

      package creative.pattern.factory.absFactory;
      
      /**
       * 抽象工廠模式測(cè)試類
       *
       */
      public class AbsFactoryDemo {
          public static void main(String[] args) {
              AbsFactory absFactory = new WeChatFactory();
              absFactory.getSender().sendMessage();
              absFactory.getSender2().sendMessage();
              ((WeChatSender2) absFactory.getSender2()).sendPicture();
      
              AbsFactory absFactory2 = new ShortMessageFactory();
              absFactory2.getSender().sendMessage();
              absFactory2.getSender2().sendMessage();
              ((ShortMessageSender2) absFactory2.getSender2()).sendPicture();
          }
      }
      
      /**
       * 定義一個(gè)發(fā)送工具的接口
       *
       */
      interface Sender {
          void sendMessage();
      }
      
      /**
       * 定義一個(gè)微信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class WeChatSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("使用微信,發(fā)送短信");
          }
      }
      
      /**
       * 定義一個(gè)微信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法,并新增自己的方法
       *
       */
      class WeChatSender2 implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("使用微信,發(fā)送短信");
          }
      
          public void sendPicture() {
              System.out.println("使用微信,發(fā)送圖片");
          }
      }
      
      /**
       * 定義一個(gè)短信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法
       *
       */
      class ShortMessageSender implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("使用短信,發(fā)送短信");
          }
      }
      
      /**
       * 定義一個(gè)短信發(fā)送工具,實(shí)現(xiàn)接口,重寫方法,并新增自己的方法
       *
       */
      class ShortMessageSender2 implements Sender {
      
          @Override
          public void sendMessage() {
              System.out.println("使用短信,發(fā)送短信");
          }
      
          public void sendPicture() {
              System.out.println("使用短信,發(fā)送圖片");
          }
      }
      
      /**
       * 抽象工廠模式
       *
       */
      interface AbsFactory {
          Sender getSender();
      
          Sender getSender2();
      }
      
      /**
       * 工廠子類,實(shí)現(xiàn)抽象工廠類,重寫相關(guān)方法,
       *
       */
      class WeChatFactory implements AbsFactory {
      
          @Override
          public Sender getSender() {
              return new WeChatSender();
          }
      
          @Override
          public Sender getSender2() {
              return new WeChatSender2();
          }
      }
      
      /**
       * 工廠子類,實(shí)現(xiàn)抽象工廠類,重寫相關(guān)方法,
       *
       */
      class ShortMessageFactory implements AbsFactory {
      
          @Override
          public Sender getSender() {
              return new ShortMessageSender();
          }
      
          @Override
          public Sender getSender2() {
              return new ShortMessageSender2();
          }
      }

      (5)代碼分析:
        對(duì)于產(chǎn)品族,定義在一個(gè)接口中,然后通過(guò)不同的子類去實(shí)現(xiàn)。擴(kuò)展時(shí),只需要實(shí)現(xiàn)接口并重寫相關(guān)方法即可,滿足開閉原則。

      (6)UML圖:

      五、JDK中工廠模式舉例(Calendar)

      1、部分源碼

      public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> {
          /**
           * Gets a calendar using the default time zone and locale. The
           * <code>Calendar</code> returned is based on the current time
           * in the default time zone with the default
           * {@link Locale.Category#FORMAT FORMAT} locale.
           *
           * @return a Calendar.
           */
          public static Calendar getInstance()
          {
              return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
          }
          
           private static Calendar createCalendar(TimeZone zone,
                                                 Locale aLocale)
          {
              CalendarProvider provider =
                  LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                                       .getCalendarProvider();
              if (provider != null) {
                  try {
                      return provider.getInstance(zone, aLocale);
                  } catch (IllegalArgumentException iae) {
                      // fall back to the default instantiation
                  }
              }
      
              Calendar cal = null;
      
              if (aLocale.hasExtensions()) {
                  String caltype = aLocale.getUnicodeLocaleType("ca");
                  if (caltype != null) {
                      switch (caltype) {
                      case "buddhist":
                      cal = new BuddhistCalendar(zone, aLocale);
                          break;
                      case "japanese":
                          cal = new JapaneseImperialCalendar(zone, aLocale);
                          break;
                      case "gregory":
                          cal = new GregorianCalendar(zone, aLocale);
                          break;
                      }
                  }
              }
              if (cal == null) {
                  // If no known calendar type is explicitly specified,
                  // perform the traditional way to create a Calendar:
                  // create a BuddhistCalendar for th_TH locale,
                  // a JapaneseImperialCalendar for ja_JP_JP locale, or
                  // a GregorianCalendar for any other locales.
                  // NOTE: The language, country and variant strings are interned.
                  if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                      cal = new BuddhistCalendar(zone, aLocale);
                  } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
                             && aLocale.getCountry() == "JP") {
                      cal = new JapaneseImperialCalendar(zone, aLocale);
                  } else {
                      cal = new GregorianCalendar(zone, aLocale);
                  }
              }
              return cal;
          }
      }

      2、源碼分析

        Calendar內(nèi)部采用簡(jiǎn)單工廠模式進(jìn)行對(duì)象的實(shí)例化。其根據(jù)不同的邏輯判斷條件來(lái)選擇實(shí)例化具體的對(duì)象。

       

      六、總結(jié):

      1、工廠模式的意義:

        將實(shí)例化對(duì)象的代碼提取出來(lái),放到一個(gè)類(工廠類)里面進(jìn)行維護(hù),使其與主項(xiàng)目解耦,提高程序的維護(hù)性與擴(kuò)展性。

      2、傳統(tǒng)模式:

        直接在需要的地方實(shí)例化某對(duì)象。擴(kuò)展代碼時(shí),需要在使用到的地方進(jìn)行修改,違反了開閉原則。

      3、簡(jiǎn)單工廠模式:

        在需要用到的地方,調(diào)用工廠類即可,擴(kuò)展代碼時(shí),修改工廠類即可,也違反了開閉原則。
      (1)簡(jiǎn)單工廠模式(普通方法):
        使用一個(gè)工廠類,在某方法中通過(guò)邏輯處理并實(shí)例化需要的對(duì)象。
      (2)簡(jiǎn)單工廠模式(靜態(tài)方法):
        將簡(jiǎn)單工廠模式(普通方法)的普通方法改為靜態(tài)方法,并通過(guò)”類名.方法名“來(lái)調(diào)用。
      (3)簡(jiǎn)單工廠模式(多方法):
        使用一個(gè)工廠類,并通過(guò)調(diào)用不同的方法去實(shí)例化不同的對(duì)象。

      4、工廠方法模式:

        使用一個(gè)工廠類接口與多個(gè)工廠實(shí)現(xiàn)類,在不同的工廠實(shí)現(xiàn)類中去實(shí)例化不同的對(duì)象。擴(kuò)展代碼時(shí),定義一個(gè)工廠實(shí)現(xiàn)類,實(shí)現(xiàn)工廠類接口并重寫相關(guān)方法即可,滿足開閉原則。可以理解為抽象工廠模式的一般形式。

      5、抽象工廠模式:

        可以理解為工廠方法模式的升級(jí)版,其在一個(gè)接口中定義了一個(gè)產(chǎn)品族的處理(多個(gè)方法),子類實(shí)現(xiàn)該接口,并重寫相關(guān)方法即可,擴(kuò)展類似于工廠方法模式,滿足開閉原則。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多