設計模式-工廠設計模式
阿新 • • 發佈:2020-09-13
背景:
在Java中,萬物皆物件。要想使用這些物件,就需要建立它,如果在使用該物件的類中都採用new方式建立該物件,會嚴重耦合,假如要更換物件,所以new該物件的地方都要做修改,這違背了軟體的開閉設計原則。 如果使用工廠來生產物件,就只和工廠打交道了,徹底和物件解耦,如果要更換物件,直接在工廠裡更換該物件即可,達到了與物件解耦的目的;所以說,工廠模式最大的優點就是:解耦工廠設計模式解決的問題:
在系統重構或增加產品時類的建立,如果類的建立放在主邏輯中。會導致修改工作量大而且在分工合作時程式碼結構化變差、書寫難度增加、程式碼通用性變差 工廠設計模式屬於建立型設計模式中的一種,他提供了建立物件的最佳方式。 簡單工廠案例: 先將產品類抽象出來,比如,蘋果和梨都屬於水果,抽象出來一個水果類Fruit,蘋果和梨就是具體的產品類,然後建立一個水果工廠,分別用來建立蘋果和梨;程式碼如下: 水果介面public蘋果interface IFruit { void get(); }
public class Apple implements IFruit { @Override public void get() { System.out.println(“apple”); } }
梨
public class Pear implements Fruit { @Override public void get() { System.out.println(“pear”); } }水果工廠
public class FruitFactory { public Fruit createFruit(String type) { if (type.equals("apple")) {//生產蘋果 return new Apple(); } else if (type.equals("pear")) {//生產梨 return new Pear(); } return null; } }使用:
FruitFactory factory = new一個非常簡單的工廠設計模式就完成了。 那麼問題來了,我想吃桃子、香蕉,我還想吃其他的水果,那不是都得建立桃子、香蕉、等等其他水果實現IFruit介面,然後在FruitFactory的createFruit修改新增建立桃子、香蕉等程式碼。顯然,每當需要新增一種水果的時候,就需要修改工廠類,這顯然違背了開閉原則。 所以簡單工廠只適合於產品物件較少,且產品固定的需求,對於產品變化無常的需求來說顯然不合適。 工廠方法設計模式: 將工廠提取成一個介面或抽象類,具體生產什麼產品由子類決定 工廠介面FruitFactory(); Apple apple = (Apple) factory.createFruit("apple");//獲得蘋果 Pear pear = (Pear) factory.createFruit("pear");//獲得梨
public interface FruitFactory { Fruit createFruit();//生產水果 }蘋果工廠
public class AppleFactory implements FruitFactory { @Override public Fruit createFruit() { return new Apple(); } }梨工廠
public class PearFactory implements FruitFactory { @Override public Fruit createFruit() { return new Pear(); } }使用
AppleFactory appleFactory = new AppleFactory();//建立蘋果工廠 PearFactory pearFactory = new PearFactory();//建立梨工廠 Apple apple = (Apple) appleFactory.createFruit();//獲得蘋果 Pear pear = (Pear) pearFactory.createFruit();//獲得梨以上這種方式,雖然解耦了,也遵循了開閉原則,問題根本還是沒有解決,如果需要的產品很多的話,需要建立非常多的工廠,所以這種方式的缺點也很明顯 抽象工廠模式 抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠建立其他工廠。該超級工廠又稱為其他工廠的工廠。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。 在抽象工廠模式中,介面是負責建立一個相關物件的工廠,不需要顯式指定它們的類。每個生成的工廠都能按照工廠模式提供物件 程式碼實現:
1)為形狀建立一個介面 Shape.java public interface Shape { void draw(); } 2)建立具體形狀類,實現形狀介面 Rectangle.java public class Rectangle implements Shape { @Override public void draw() { System.out.println("Rectangle"); } } Square.java public class Square implements Shape { @Override public void draw() { System.out.println("Square "); } } 3)為顏色建立一個介面 Color.java public interface Color{ void fill(); } 4)建立具體顏色類,實現顏色介面 Red.java public class Red implements Color{ @Override public void fill() { System.out.println("Red"); } } Blue.java public class Blueimplements Color{ @Override public void fill() { System.out.println("Blue"); } } 5)為 Color 和 Shape 物件建立抽象類來獲取工廠 AbstractFactory.java public abstract class AbstractFactory { public abstract Color getColor(String color); public abstract Shape getShape(String shape) ; } 6)建立Color和Shape 對應的工廠,都整合AbstractFactory //ShapeFactory生產shape public class ShapeFactory extends AbstractFactory{ @Override public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } @Override public Color getColor(String color) { return null; } } //ColorFactory生產color public class ColorFactory extends AbstractFactory{ @Override public Shape getShape(String shapeType){ return null; } @Override public Color getColor(String color) { if(color == null){ return null; } if(color.equalsIgnoreCase("RED")){ return new Red(); }else if(color.equalsIgnoreCase("BLUE")){ return new Blue(); } return null; } } 7)建立一個工廠創造器/生成器類,通過傳遞形狀或顏色資訊來獲取工廠 public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("SHAPE")){ return new ShapeFactory(); } else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } } 8)使用 FactoryProducer 來獲取 AbstractFactory,通過傳遞型別資訊來獲取實體類的物件 public class AbstractFactoryPatternDemo { public static void main(String[] args) { //獲取形狀工廠 AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //獲取形狀為 Square的物件 Shape shape1 = shapeFactory.getShape("SQUARE"); //呼叫 Square的 draw 方法 shape1.draw(); //獲取形狀為 Rectangle 的物件 Shape shape2 = shapeFactory.getShape("RECTANGLE"); //呼叫 Rectangle 的 draw 方法 shape2.draw(); //獲取顏色工廠 AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR"); //獲取顏色為 Red 的物件 Color color1 = colorFactory.getColor("RED"); //呼叫 Red 的 fill 方法 color1.fill(); //獲取顏色為 Blue 的物件 Color color2 = colorFactory.getColor("BLUE"); //呼叫 Green 的 fill 方法 color2.fill(); } }三種工廠方式總結: 1、對於簡單工廠和工廠方法來說,兩者的使用方式實際上是一樣的,如果對於產品的分類和名稱是確定的,數量是相對固定的,推薦使用簡單工廠模式; 2、抽象工廠用來解決相對複雜的問題,適用於一系列、大批量的物件生產;