1. 程式人生 > 實用技巧 >設計模式-工廠設計模式

設計模式-工廠設計模式

背景:

在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
FruitFactory(); Apple apple = (Apple) factory.createFruit("apple");//獲得蘋果 Pear pear = (Pear) factory.createFruit("pear");//獲得梨
一個非常簡單的工廠設計模式就完成了。 那麼問題來了,我想吃桃子、香蕉,我還想吃其他的水果,那不是都得建立桃子、香蕉、等等其他水果實現IFruit介面,然後在FruitFactory的createFruit修改新增建立桃子、香蕉等程式碼。顯然,每當需要新增一種水果的時候,就需要修改工廠類,這顯然違背了開閉原則。 所以簡單工廠只適合於產品物件較少,且產品固定的需求,對於產品變化無常的需求來說顯然不合適。 工廠方法設計模式: 將工廠提取成一個介面或抽象類,具體生產什麼產品由子類決定 工廠介面
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、抽象工廠用來解決相對複雜的問題,適用於一系列、大批量的物件生產;