創建型模式————工廠模式(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