Java-工廠設計模式

  • 2019 年 10 月 14 日
  • 筆記

一、關於工廠設計模式

介紹設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,

    並且是通過使用一個共同的介面來指向新創建的對象。

意圖:定義一個創建對象的介面,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。

主要解決:主要解決介面選擇的問題。

何時使用:我們明確地計劃不同條件下創建不同實例時。

如何解決:讓其子類實現工廠介面,返回的也是一個抽象的產品。

分類:普通簡單工廠、多個方法的簡單工廠、多個靜態方法的簡單工廠、工廠設計模式。

 

二、程式碼實現

  簡單工廠:就是建立一個工廠類,對實現了同一介面的一些類進行實例的創建。首先看下關係圖

  

舉例如下:(我們舉一個發送郵件和簡訊的例子)

首先,創建二者的共同介面:

Sender

package pers.hupo.hupow.factory;  /**   * @author hupo   * 創建一個介面   * */  public interface Sender {      void Send();  }

 

其次,創建實現類:

MailSender

package pers.hupo.hupow.factory;    /**   * @author hupo   * Sender實現類   * */  public class MailSender implements Sender {      @Override      public void Send() {          System.out.println("this mail message");      }  }

 

SmsSender

package pers.hupo.hupow.factory;    /**   * @author hupo   * Sender實現類   * */  public class SmsSender implements Sender {      @Override      public void Send() {          System.out.println("this sms message");      }  }

 

最後,建工廠類

package pers.hupo.hupow.factory;    /**   * @author hupo   * 工廠類   * */  public class SendFactory {        public Sender produce(String type) {          if ("mail".equals(type)) {              return new MailSender();          }          if ("sms".equals(type)) {              return new SmsSender();          }          return null;      }  }

 

測試方法

package pers.hupo.hupow.factory;      public class FactoryTest {      public static void main(String[] args) {

     SendFactory sendFactory
= new SendFactory(); Sender sender = sendFactory.produce("sms"); sender.Send(); } }

 

輸出結果:

this sms message

 

  多個方法的簡單工廠:是對普通工廠方法模式的改進,在普通工廠方法模式中,如果傳遞的字元串出錯,則不能正確創建對象,

             而多個工廠方法模式是提供多個工廠方法,分別創建對象。關係圖如下

 

 

 

 將工廠類改動一些 如下:

package pers.hupo.hupow.factory;    /**   * @author hupo   * 工廠類   * */  public class SendFactory {      /*       * 多方法的簡單工廠       */       public Sender produceMail() {          return new MailSender();       }         public Sender produceSms() {          return new SmsSender();       }  }

修改一下測試類

 SendFactory sendFactory = new SendFactory();   Sender sender = sendFactory.produceMail();   sender.Send();

輸出結果:

  this mail message

   

  多個靜態方法簡單工廠:將上面的多個工廠類里的方法置為靜態的,不需要創建實例,直接調用即可。如下

package pers.hupo.hupow.factory;    /**   * @author hupo   * 工廠類   * */  public class SendFactory {      /*       * 靜態多方法工廠       * */      public static Sender produceMail() {          return new MailSender();      }        public static Sender produceSms() {          return new SmsSender();      }    }

測試

      /*靜態多方法*/          Sender sender = SendFactory.produceMail();          sender.Send();

輸出:

this mail messageb

 

總體來說,簡單工廠模式適合:凡是出現了大量的產品需要創建,並且具有共同的介面時,可以通過工廠方法模式進行創建。在以上的三種模式中,

第一種如果傳入的字元串有誤,不能正確創建對象(當然你可以做一個返回報錯資訊的類),第三種相對於第二種,不需要實例化工廠類,所以,大多數情況下,我們會選用第三種——靜態工廠方法模式。

 

三、工廠方法模式(Factory Method)

簡單工廠模式有一個問題就是,類的創建依賴工廠類,也就是說,如果想要拓展程式,必須對工廠類進行修改,這違背了閉包原則。

所以,從設計角度考慮,有一定的問題,如何解決?就用到工廠方法模式,創建一個工廠介面和創建多個工廠實現類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的程式碼。

 

 

首先還是創建發送資訊端的介面

Sender

package pers.hupo.hupow.FactoryMethod;    /**   * @author hupo   * 工廠方法設計模式-資訊介面   */  public interface Sender {      void Send();  }

兩個實現類

MailSender

package pers.hupo.hupow.FactoryMethod;    /**   * @author hupo   * 工廠方法設計模式-實現類   * */  public class MailSender implements Sender {      @Override      public void Send() {          System.out.println("this is mailSender");      }  }

SmsSender

package pers.hupo.hupow.FactoryMethod;    /**   * @author hupo   * 工廠方法設計模式-實現類   * */  public class SmsSender implements Sender {      @Override      public void Send() {          System.out.println("this is smsSender");      }  }

 

 然後再來創造工廠類介面(大內統管( ̄▽ ̄)”

Provider

package pers.hupo.hupow.FactoryMethod;    /**   * @author hupo   * 工廠方法設計模式-工廠類介面   * */  public interface Provider {      Sender produce();  }

實現類工廠

SendMailFactory

package pers.hupo.hupow.FactoryMethod;    /**   * @author hupo   * 工廠類設計方法-實現方法   * */  public class SendMailFactory implements Provider {      @Override      public Sender produce() {          return new MailSender();      }  }

SendSmsFactory

package pers.hupo.hupow.FactoryMethod;    /**   * @author hupo   * 介面實現方法   * */  public class SendSmsFactory implements Provider {      @Override      public Sender produce() {          return new SmsSender();      }  }

完成之後寫個測試類來試試

package pers.hupo.hupow.FactoryMethod;    /**   * @author hupo   * 測試類   * */  public class FactoryMethodTest {      public static void main(String[] args) {          Provider provider = new SendMailFactory();          Sender sender = provider.produce();          sender.Send();      }  }

輸出結果

this is mailSender

 

加個工廠類擴展試試

添加哲學家van 和Billy 繼承sender

van

package pers.hupo.hupow.FactoryMethod;    public class VanSender implements Sender {      @Override      public void Send() {          System.out.println("f♂ck y♂u");      }  }

View Code

Billy

package pers.hupo.hupow.FactoryMethod;    public class BillySender implements Sender {      @Override      public void Send() {          System.out.println("帕秋莉♂GO");      }  }

View Code

然後使用SendBillyFactory 繼承Provider

package pers.hupo.hupow.FactoryMethod;    public class SendBillyFactory implements Provider {      @Override      public Sender produce() {          return new BillySender();      }  }

View Code

測試類

    /*哲學家測試*/          Provider provider = new SendBillyFactory();          Sender sender = provider.produce();          sender.Send();

View Code

輸出:

帕秋莉♂GO

其實這個模式的好處就是,如果你現在想增加一個功能:發及時資訊,則只需做一個實現類,實現Sender介面,同時做一個工廠類,實現Provider介面,就OK了,無需去改動現成的程式碼。這樣做,拓展性較好!