創建型模式————工廠模式(2.2)

  • 2019 年 10 月 6 日
  • 筆記

什麼是工廠模式?

工廠模式是創建型模式的一種,工廠是用來生產的,而在Java里,是用來生產對象實例的。

和單例模式相似,工廠模式同樣聚焦於在考慮整個軟體構建的情況下合理創建對象,從而保證軟體的擴展性和穩定性。

工廠模式分為三種:

  • 簡單工廠模式
  • 工廠方法模式
  • 抽象工廠模式

簡單工廠模式(實現服務端自擴展)

服務端:提供程式碼的人(作者)

客戶端:使用程式碼的人(用戶)

【對於程式設計師來說,自己是作者,用戶是普通人;那麼對於發明語言,框架的人來說,創建者是作者,而普通程式設計師是用戶】

假設沒有使用簡單工廠模式:

定義一個Coder介面,然後定義JavaCoder和PythonCoder實現Coder介面。客戶端通過new來創建對象。(耦合)

//服務端  interface Coder {        void express();  }    class JavaCoder implements Coder  {      @Override      public void express()      {          System.out.println("I am a Java Coder");        }  }    class PythonCoder implements Coder  {        @Override      public void express()      {          System.out.println("I am a Python Coder");        }  }    //===============================================================================  public class ProductManager     //客戶端  {      public static void main(String[] args) {            Coder javaCoder = new JavaCoder();          javaCoder.express();          }        }

當服務端需要擴展一個類時:需要進行1,2兩步

//服務端  interface Coder {        void express();  }    class JavaCoder implements Coder  {      @Override      public void express()      {          System.out.println("I am a Java Coder");        }  }    class PythonCoder implements Coder  {        @Override      public void express()      {          System.out.println("I am a Python Coder");        }  }      class GoCoder implements Coder    //1.服務端擴展  {        @Override      public void express()      {          System.out.println("I am a Go Coder");        }  }  //===============================================================================  public class ProductManager     //客戶端  {      public static void main(String[] args) {            Coder javaCoder = new JavaCoder();          javaCoder.express();            Coder goCoder = new GoCoder();   //2.客戶端跟著修改          goCoder.express();      }        }

服務端和客戶端處於高度耦合狀態。(服務端的變化會引起客戶端的變化)

使用簡單工廠模式:(如果服務端要擴展一個GoCoder,客戶端無需做修改)

//服務端  interface Coder {        void express();  }    class JavaCoder implements Coder  {      @Override      public void express()      {          System.out.println("I am a Java Coder");        }  }    class PythonCoder implements Coder  {        @Override      public void express()      {          System.out.println("I am a Python Coder");        }  }      class GoCoder implements Coder    //1.服務端擴展  {        @Override      public void express()      {          System.out.println("I am a Go Coder");        }  }    class SimpleFactory  {        //使用靜態內部類實現單例模式      private static class StaticClassInnerInstance {          private static final SimpleFactory INSTANCE = new SimpleFactory();      }          public static SimpleFactory getInstance() {          return StaticClassInnerInstance.INSTANCE;      }        public Coder createCoder(String language)      {          Coder coder = null;          if(language.equals("Java"))          {              coder= new JavaCoder();            }          else if(language.equals("Python"))          {              coder= new PythonCoder();          }          else if(language.equals("Go"))  //2.擴展條件          {              coder= new GoCoder();          }          return coder;      }  }  //===============================================================================  public class ProductManager     //客戶端  {        public static void main(String[] args) {            SimpleFactory factory = SimpleFactory.getInstance();          Coder javaCoder = factory.createCoder("Java");          javaCoder.express();          }        }

簡單工廠UML類圖:

簡單工廠的優缺點:

優點:

解決了服務端與客戶端的耦合問題,實現了服務端的自擴展。

缺點:

當客戶端需要進行功能擴展時,無法在SimpleFactory中添加對應修改程式碼。

簡單工廠可以完成服務端的自擴展,但客戶端只能調用,無法擴展。

工廠方法模式(實現客戶端自擴展)

//服務端  interface Coder {        void express();  }    class JavaCoder implements Coder  {      @Override      public void express()      {          System.out.println("I am a Java Coder");        }  }    class PythonCoder implements Coder  {        @Override      public void express()      {          System.out.println("I am a Python Coder");        }  }      class GoCoder implements Coder    //1.服務端擴展  {        @Override      public void express()      {          System.out.println("I am a Go Coder");        }  }    interface CoderFactory   //抽象出CoderFactory  {      public Coder createCoder(String language);  }    class ServerFactory implements CoderFactory  {        private static class StaticClassInnerInstance {          private static final ServerFactory INSTANCE = new ServerFactory();      }        public static ServerFactory getInstance() {          return StaticClassInnerInstance.INSTANCE;      }        @Override      public Coder createCoder(String language)      {          Coder coder = null;          if(language.equals("Java"))          {              coder= new JavaCoder();            }          else if(language.equals("Python"))          {              coder= new PythonCoder();          }          else if(language.equals("Go"))  //2.擴展條件          {              coder= new GoCoder();          }          return coder;      }  }  //===============================================================================    class RustCoder implements Coder  {      @Override      public void express()      {          System.out.println("I am a Rust Coder");        }  }    class ClientFactory implements CoderFactory  {      private static class StaticClassInnerInstance1 {          private static final ClientFactory INSTANCE = new ClientFactory();      }        public static ClientFactory getInstance() {          return ClientFactory.StaticClassInnerInstance1.INSTANCE;      }        @Override      public Coder createCoder(String language)      {            return new RustCoder();      }  }    public class ProductManager     //客戶端  {        public static void main(String[] args) {           ClientFactory clientFactory = ClientFactory.getInstance();         Coder coder = clientFactory.createCoder("Rust");         coder.express();      }  }

工廠方法UML類圖:

工廠方法模式的優缺點:

優點:實現了客戶端的自擴展。

缺點:無法擴展多個產品。

抽象工廠模式(實現產品簇)

適應多個產品,加入設計師。

抽象工廠中可以生產多個產品,產品之間存在內在聯繫。比如說JavaCoder對應JavaDesigner。

而實例化的工廠就是根據這種內在聯繫來劃分的。

同一個工廠的產品屬於一個產品簇,不同產品簇之間是不能互相組合的。比如說GoDesigner和PythonCoder是不能組合到一個工廠里的。

//服務端  interface Coder {        void express();  }  interface Designer {        void express();  }      class JavaCoder implements Coder  {      @Override      public void express()      {          System.out.println("I am a Java Coder");        }  }    class PythonCoder implements Coder  {        @Override      public void express()      {          System.out.println("I am a Python Coder");        }  }      class GoCoder implements Coder  {        @Override      public void express()      {          System.out.println("I am a Go Coder");        }  }    class JavaDesigner implements Designer  {      @Override      public void express()      {          System.out.println("I am a Java Designer!");        }  }  class PythonDesigner implements Designer  {      @Override      public void express()      {          System.out.println("I am a Python Designer!");        }  }  class GoDesigner implements Designer  {      @Override      public void express()      {          System.out.println("I am a Go Designer!");        }  }    interface ProductFactory  {      public Coder createCoder();      public Designer createDesigner();    }    class GoFactory implements ProductFactory  {        private static class StaticClassInnerInstance {          private static final GoFactory INSTANCE = new GoFactory();      }        public static GoFactory getInstance() {          return StaticClassInnerInstance.INSTANCE;      }        @Override      public Coder createCoder()      {                Coder coder= new GoCoder();            return coder;      }      @Override      public Designer createDesigner()      {          Designer designer= new GoDesigner();            return designer;      }    }    class JavaFactory implements ProductFactory  {        private static class StaticClassInnerInstance {          private static final JavaFactory INSTANCE = new JavaFactory();      }        public static JavaFactory getInstance() {          return StaticClassInnerInstance.INSTANCE;      }        @Override      public Coder createCoder()      {            Coder coder= new JavaCoder();            return coder;      }      @Override      public Designer createDesigner()      {          Designer designer= new JavaDesigner();            return designer;      }    }  //===============================================================================        public class ProductManager     //客戶端  {        public static void main(String[] args) {          JavaFactory javaFactory = JavaFactory.getInstance();          Coder coder =javaFactory.createCoder();          Designer designer = javaFactory.createDesigner();          coder.express();          designer.express();              }        }

抽象工廠UML類圖:

工廠模式總結

簡單工廠模式:適用客戶端無需擴展的應用場景

工廠方法模式:適合客戶端創建單個產品的應用場景

抽象工廠模式:適合創建多個產品的應用場景(但產品類別需要固定)

————————————————————————————————————-2019.8.11