您好,登錄后才能下訂單哦!
本篇內容介紹了“Java設計模式的工廠模式怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
在Java應用程序中對象無處不在,這些對象都需要進行創建,如果創建的時候直接new對象,那么如果我們要更換對象,所有new對象的地方都需要進行更改。違背了軟件設計原則中的開閉原則。如果我們使用工廠生產對象,只需要在工廠中關注對象的改變即可,達到了與對象解耦的目的,工廠模式最大的特點就是解耦合
補充:
開閉原則: 對擴展開放,對修改關閉。在程序需要進行擴展的時候,不能去修改原有的代碼,實現一個熱插拔的效果。是為了使程序的擴展性好,易于維護和升級。
抽象產品: 定義了產品的規范,描述了產品的主要特性和功能。
具體產品: 實現或者繼承抽象產品的子類
具體工廠: 提供了創建產品的方法,調用者通過該方法來創建產品。
以點咖啡為例:
咖啡抽象類
public abstract class Coffee { /** * 獲取咖啡類型 * @return */ public abstract String getName(); /** *加糖 */ public void addSugar(){ System.out.println("加糖"); } /** *加奶 */ public void addMilk(){ System.out.println("加奶"); } }
美式咖啡類
public class AmericanCoffee extends Coffee{ @Override public String getName(){ return "美式咖啡"; } }
拿鐵咖啡類
public class LatteCoffee extends Coffee { @Override public String getName(){ return "拿鐵咖啡"; } }
咖啡工廠類
public class CoffeeFactory { public Coffee createCoffee(String type){ Coffee coffee = null; if("american".equals(type)){ coffee = new AmericanCoffee(); }else if("latten".equals(type)){ coffee = new LatteCoffee(); }else{ throw new RuntimeException("沒有此類型的咖啡"); } return coffee; } }
咖啡店類
public class CoffeeStore { public Coffee orderCoffee(String type){ CoffeeFactory factory = new CoffeeFactory(); //調用生產咖啡的方法 Coffee coffee = factory.createCoffee(type); coffee.addMilk(); coffee.addSugar(); return coffee; } }
測試類
public class Test { public static void main(String[] args) { CoffeeStore coffeeStore = new CoffeeStore(); Coffee coffee = coffeeStore.orderCoffee("latten"); System.out.println(coffee.getName()); } }
類圖
咖啡工廠負責生產咖啡(具體工廠),咖啡店通過咖啡工廠選取咖啡
其實簡單工廠是大家在實際寫代碼的時候經常用到的,雖然簡單工廠實現了咖啡店與咖啡的耦合,但是可以明顯看到咖啡與咖啡工廠又耦合起來了,后期如果增加咖啡的新品種,我們需要修改咖啡工廠的代碼,這又違背了“開閉原則”。
注意:
簡單工廠和不使用工廠是有很大區別的,如果咖啡店有多個,不使用工廠如果遇到新增咖啡需要修改所有咖啡店,但是使用工廠只需要修改咖啡工廠,類似于將所有咖啡店抽取出一個抽象的咖啡店。
優點:
封裝了創建對象的過程,可以通過參數直接獲取對象,把對象的創建和業務邏輯層分開,這樣可以避免之后修改客戶代碼,如果需要實現新產品直接修改工廠類,更容易擴展。
缺點:
增加新產品時還需要修改工廠類的代碼,違背了“開閉原則”。
靜態工廠,將工廠類中創建對象的功能定義為靜態的,這樣不需要再創建工廠類,直接通過類名調用靜態方法,類似于工具類
public class CoffeeFactory { //靜態方法 public static Coffee createCoffee(String type){ Coffee coffee = null; if("american".equals(type)){ coffee = new AmericanCoffee(); }else if("latten".equals(type)){ coffee = new LatteCoffee(); }else{ throw new RuntimeException("沒有此類型的咖啡"); } return coffee; } }
對工廠進行抽象,每一種產品對應一個具體工廠,新增產品只需要再新增對應的具體工廠,符合”開閉原則“
抽象工廠: 提供創建產品的接口,調用者通過它訪問具體工廠的工廠方法來創建產品
具體工廠: 主要是實現抽象工廠中的抽象方法,完成具體產品的創建
抽象產品: 定義了產品的規范,描述了產品的主要特性和功能
具體產品: 實現抽象產品所定義的接口,由具體工廠來創建,與具體工廠之間一一對應
抽象咖啡類和具體咖啡類不變
咖啡工廠(抽象工廠)
public interface CoffeeFactory { /** * 創建咖啡 * @return */ Coffee createCoffee(); }
美式咖啡工廠(具體工廠)
public class AmericanCoffeeFactory implements CoffeeFactory{ //美式咖啡工廠對象,專門生產美式咖啡 @Override public Coffee createCoffee() { return new AmericanCoffee(); } }
拿鐵咖啡工廠(具體工廠)
public class LatteCoffeeFactory implements CoffeeFactory{ //拿鐵咖啡工廠對象,專門生產拿鐵咖啡 @Override public Coffee createCoffee() { return new LatteCoffee(); } }
咖啡店
public class CoffeeStore { private CoffeeFactory factory; public void setFactory(CoffeeFactory factory) { this.factory = factory; } /** * 點咖啡 */ public Coffee orderCoffee() { Coffee coffee = factory.createCoffee(); coffee.addSugar(); coffee.addMilk(); return coffee; } }
測試類
public class Test { public static void main(String[] args) { //創建咖啡店對象 CoffeeStore coffeeStore = new CoffeeStore(); //創建工廠對象 CoffeeFactory factory = new AmericanCoffeeFactory(); coffeeStore.setFactory(factory); //點咖啡 Coffee coffee = coffeeStore.orderCoffee(); System.out.println(coffee.getName()); } }
類圖
我們只需要知道所點咖啡具體對應的工廠對象,通過咖啡店調用對應的工廠,由工廠創建咖啡對象實現點咖啡的過程
優點:
用戶只需要知道具體工廠就可以獲得所需產品,無需知道產品的具體創建過程
在系統新增產品時只需要添加具體產品類和對應的具體工廠類,無需對原工廠進行修改符合“開閉原則”
缺點:
每增加一個產品就要增加一個對應的具體工廠類,增加的系統的復雜性。如果具體產品種類過多,那么大量的工廠類不僅難以管理,而且也會造成程序中創建的對象過多,嚴重影響內存性能
抽象工廠: 提供創建產品的接口,包含多個創建產品的方法,可以創建多個不同等級的產品
具體工廠: 主要是實現抽象工廠中的多個抽象方法,完成具體產品的創建
抽象產品: 定義了產品的規范,描述了產品的主要特性和功能,抽象工廠模式有多個抽象產品
具體產品: 實現抽象產品所定義的接口,由具體工廠來創建,與具體工廠是多對一關系
咖啡抽象類
public abstract class Coffee { /** * 獲取咖啡類型 * @return */ public abstract String getName(); /** *加糖 */ public void addSugar(){ System.out.println("加糖"); } /** *加奶 */ public void addMilk(){ System.out.println("加奶"); } }
美式咖啡類
public class AmericanCoffee extends Coffee{ @Override public String getName(){ return "美式咖啡"; } }
拿鐵咖啡類
public class LatteCoffee extends Coffee { @Override public String getName(){ return "拿鐵咖啡"; } }
甜品抽象類
public abstract class Dessert { //甜品抽象類 public abstract void show(); }
抹茶慕斯類
public class MatchaMousse extends Dessert{ //抹茶慕斯類 @Override public void show() { System.out.println("抹茶慕斯"); } }
提拉米蘇類
public class Tiramisu extends Dessert{ //提拉米蘇類 @Override public void show() { System.out.println("提拉米蘇"); } }
甜品工廠
public interface DessertFactory { /** * 生產咖啡 * @return */ Coffee createCoffee(); /** * 生產甜品 * @return */ Dessert createDessert(); }
美式風味甜品工廠類
public class AmericanDessertFactory implements DessertFactory{ /** *美式風味甜品工廠 * 可以生產美式咖啡和抹茶慕斯 */ @Override public Coffee createCoffee() { return new AmericanCoffee(); } @Override public Dessert createDessert() { return new MatchaMousse(); } }
意大利風味甜品工廠類
public class ItalyDessertFactory implements DessertFactory { /** *意大利風味甜品工廠 * 可以生產拿鐵咖啡和提拉米蘇 */ @Override public Coffee createCoffee() { return new LatteCoffee(); } @Override public Dessert createDessert() { return new Tiramisu(); } }
測試類
public class Test { public static void main(String[] args) { //ItalyDessertFactory factory = new ItalyDessertFactory(); AmericanDessertFactory factory = new AmericanDessertFactory(); Coffee coffee = factory.createCoffee() Dessert dessert = factory.createDessert(); System.out.println(coffee.getName()); dessert.show(); } }
類圖
由類圖可見,抽象工廠不再是一個具體工廠對應一個產品,而是一個具體工廠對應一個產品族。如果需要增加一個產品族只需加對應的工廠類,符合”開閉原則“
優點:
在工廠方法的基礎上減少了部分對象的創建,適合于每次只使用同一產品族的對象這類應用場景
缺點:
當產品族中需要增加一個產品時,所有工廠都要修改
配置文件+簡單工廠
通過工廠模式+配置文件的方式解除工廠對象和產品對象的耦合。在工廠類中加載配置文件的全類名,通過反射創建對象并存儲在容器中,如果需要直接從容器中獲取(Spring IOC原理)
1.定義配置文件
american = com.xue.config_factory.AmericanCoffee latten = com.xue.config_factory.LatteCoffee
2.改進工廠類
public class CoffeeFactory { /** * 加載配置文件,獲取配置文件中配置的全類名,并創建該類的對象進行存儲 */ //1.定義容器對象存儲咖啡對象 private static HashMap<String, Coffee> map = new HashMap<>(); //2.加載配置文件 static { //創建 Properties對象 Properties properties = new Properties(); //調用properties對象中的load方法進行配置文件的加載 InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties"); try { properties.load(is); //從properties中獲取全類名 Set<Object> keys = properties.keySet(); for (Object key : keys) { String className = properties.getProperty((String) key); //通過反射創建對象 Class class1 = Class.forName(className); Coffee coffee = (Coffee) class1.newInstance(); //將名稱和對象存儲在容器中 map.put((String) key,coffee); } } catch (Exception e) { e.printStackTrace(); } } //根據名稱獲取對象 public static Coffee createCoffee(String name) { return map.get(name); } }
靜態成員變量用來存儲創建的對象(鍵存儲的是名稱,值存儲的是對應的對象),而讀取配置文件和創建對象寫在靜態代碼塊中只需要執行一次
測試類
public class Test { public static void main(String[] args) { Coffee coffee = CoffeeFactory.createCoffee("american"); System.out.println(coffee.getName()); System.out.println("------------"); Coffee latten = CoffeeFactory.createCoffee("latten"); System.out.println(latten.getName()); } }
成功!!!
“Java設計模式的工廠模式怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。