java設計模式-工廠方法模式

燕雀安知毛驢之志發表於2020-12-25

工廠方法模式詳解

  今天我們主要學習Java設計模式中的工廠方法模式,如果你看過我之前寫的簡單工廠模式會更容易理解下面的講解,為了便於理解工廠方法模式我依然用食品加工廠為案例。

一,概述

  工廠方法模式去掉了簡單工廠模式中工廠方法的靜態屬性使得它可以被子類繼承。這樣在簡單工廠模式裡集中在工廠方法上的壓力可以由工廠方法模式裡不同  的工廠子類來分擔。

  工廠方法模式使用繼承自抽象工廠角色的多個子類來代替簡單工廠模式中的“頂級類”。這樣便分擔了物件建立的壓力;避免工廠類中用邏輯判斷來決定建立物件,  而且這樣使得結構變得相當靈活當有新的產品產生時,只要按照抽象產品角色、抽象工廠角色提供的規則來生成,那麼就可以被客戶使用,而不必去修改任何已有的  程式碼,可以看出工廠方法模式符合開閉原則

二,結構圖

  • AbstractProduct 類:抽象產品類,工廠方法模式所建立的所有物件的父類,它負責描述所有例項所共有的公共介面
  • Berr 類和 Drinks 類:具體產品類,是簡單工廠模式的建立目標
  • AbstractFactory 類:抽象工廠類,這是工廠方法模式的核心,是具體工廠角色必須實現的介面或者必須繼承的父類。在java中它由抽象類或者介面來實現
  • BerrFactory 類和 DrinksFactory 類:具體工廠類,它含有和具體業務邏輯有關的程式碼。由應用程式呼叫以建立對應的具體產品的物件

 三,舉例說明

  這裡我們以食品加工廠來舉例,假設有一個食品加工廠,主要加工啤酒飲料礦泉水,根據需求,我們就需要用一個單獨的類來專門生產啤酒飲料礦泉水,因為我  們的工廠後期一定會做大做強,所以我們就要考慮這個設計方案對後續的業務擴充影響,我們廠子要求設計之初必須要在不影響現有業務基礎上,能靈活擴充新的制  造業務,根據食品加工廠的需求,我們採用了工廠方法設計模式

 四,具體程式碼實現

  第一步:設計我們產品也就是我們要生產的物件,按照結構我們設計程式碼如下

  抽象產品類程式碼所有產品的父類,程式碼如下:

package pattern.factory.product;
/**
 * 建立產品抽象類也可以用介面來定義
 * @author ningbeibei
 *
 */
public abstract class AbstractProduct {
    //獲取產品抽象方法,需要具體的實現類來實現
    public abstract void getFood();
}

   具體產品Berr(啤酒),程式碼如下:

package pattern.factory.product;

/**
 * 啤酒具體啤酒類繼承自AbstractProduct類
 * @author ningbeibei
 */
public class Berr extends AbstractProduct {
    @Override
    public void getFood() {
        System.out.println("啤酒");
    };
}

   具體產品Drinks (飲料),程式碼如下:

package pattern.factory.product;

/**
 * 具體飲料類繼承自AbstractProduct
 * @author ningbeibei
 */
public class Drinks extends AbstractProduct {

    @Override
    public void getFood() {
        System.out.println("飲料");
    }
}

  第二步:設計製造產品的工廠,這也是工廠方法模式最總要的環節

  建立工廠抽象類,程式碼如下:

package pattern.factory.factorymill;
import pattern.factory.product.AbstractProduct;
/**
 * 抽象工廠類,食品加工廠需要進行抽象設計
 * @author ningbeibei
 *
 */
public abstract class AbstractFactory {
    //這個抽象方法返回一個產品物件,
    public abstract AbstractProduct createProduct(); 
}

  建立具體啤酒製造工廠類BerrFactory,程式碼如下:

package pattern.factory.factorymill;

import pattern.factory.product.AbstractProduct;
import pattern.factory.product.Berr;
/**
 * 專門知道啤酒的工廠,這個類實現自 AbstractFactory抽象類
 * 返回一個啤酒產品物件
 * @author ningbeibei
 *
 */
public class BerrFactory extends AbstractFactory {
    
    //實現抽象工廠返回啤酒
    @Override
    public AbstractProduct createProduct() {
        return new Berr();
    }
}

  建立具體飲料製造工廠類,程式碼如下:

package pattern.factory.factorymill;

import pattern.factory.product.AbstractProduct;
import pattern.factory.product.Drinks;

/**
 * 專門製造飲料工廠,繼承自AbstractFactory抽象類
 * @author ningbeibei
 */
public class DrinksFactory extends AbstractFactory {

    //返回飲料物件
    @Override
    public AbstractProduct createProduct() {
        return new Drinks();
    }
}

  第三步:編寫測試類進行測試驗證

 

package pattern.factory;

import pattern.factory.factorymill.BerrFactory;
import pattern.factory.factorymill.DrinksFactory;
import pattern.factory.product.AbstractProduct;
/**
 * 工廠方法模式測試類
 * @author ningbeibei
 */
public class test {

    public static void main(String[] args) {
        //先建立啤酒工廠
        BerrFactory berrfactory = new BerrFactory();
        //呼叫啤酒工廠中createProduct()方法,建立啤酒物件並返回
        AbstractProduct product = berrfactory.createProduct();
        //輸出啤酒
        product.getFood();
        
        //先建立飲料工廠
        DrinksFactory drinksfactory = new DrinksFactory();
        //呼叫飲料工廠中createProduct()方法,建立飲料物件並返回
        AbstractProduct drinksproduct = drinksfactory.createProduct();
        //輸出飲料
        drinksproduct.getFood();
    }
}

 

  測試結果:

五,如何擴充套件新的產品

  隨著食品加工的規模擴張,我們食品加工廠想製造更多的產品,現在想製造礦泉水,根據設計之初的構想,不管後期業務擴充套件何種產品都不會動搖現有的程式碼,也就是不違背工廠模式的開閉原則

  1.新增產品礦泉水類並繼承抽象產品類,程式碼如下:

package pattern.factory.product;

/**
 * 新增礦泉水產品,同樣繼承自產品抽象類AbstractProduct
 * @author ningbeibei
 *
 */
public class Water extends AbstractProduct {

    @Override
    public void getFood() {
        System.out.println("礦泉水");
    }
}

  2.新增具體制造礦泉水工廠類並繼承抽象類AbstractFactory,程式碼如下:

 

package pattern.factory.factorymill;

import pattern.factory.product.AbstractProduct;
import pattern.factory.product.Water;
/**
 * 新增礦泉水製造工廠
 * 繼承自AbstractFactory抽象類
 * @author ningbeibei
 *
 */
public class WaterFactory extends AbstractFactory{

    //製造礦泉水物件並返回
    @Override
    public AbstractProduct createProduct() {
        return new Water();
    }
}

 

  3.測試類編寫,程式碼如下:

package pattern.factory;

import pattern.factory.factorymill.BerrFactory;
import pattern.factory.factorymill.DrinksFactory;
import pattern.factory.factorymill.WaterFactory;
import pattern.factory.product.AbstractProduct;
/**
 * 工廠方法模式測試類
 * @author ningbeibei
 */
public class test {

    public static void main(String[] args) {
        //先建立啤酒工廠
        BerrFactory berrfactory = new BerrFactory();
        //呼叫啤酒工廠中createProduct()方法,建立啤酒物件並返回
        AbstractProduct product = berrfactory.createProduct();
        //輸出啤酒
        product.getFood();
        
        //先建立飲料工廠
        DrinksFactory drinksfactory = new DrinksFactory();
        //呼叫飲料工廠中createProduct()方法,建立飲料物件並返回
        AbstractProduct drinksproduct = drinksfactory.createProduct();
        //輸出飲料
        drinksproduct.getFood();
        
        //這個是新增產品礦泉水
        WaterFactory waterfactory = new WaterFactory();
        //呼叫礦泉水工廠中createProduct()方法,建立礦泉水物件並返回
        AbstractProduct waterproduct = waterfactory.createProduct();
        //輸出礦泉水
        waterproduct.getFood();
    }
}

  4.測試結果:

 

 

 六,工廠方法模式優缺點

  缺點:

  • 類的個數容易過多,增加複雜度
  • 增加了系統的抽象性和理解難度
  • 抽象產品只能生產一種產品,此弊端可使用抽象工廠模式解決  

 優點:

  • 使用者只需要知道具體工廠的名稱就可得到所要的產品,無須知道產品的具體建立過程
  • 靈活性增強,對於新產品的建立,只需多寫一個相應的工廠類
  • 典型的解耦框架。高層模組只需要知道產品的抽象類,無須關心其他實現類,滿足迪米特法則、依賴倒置原則和里氏替換原則

 

七,學習思路

  簡單工廠模式===》而後工廠方法模式====》最後抽象工廠模式

  由淺入深的學習在才能理解的更深更全面而後方能融會貫通

  寫的不足之處望批評指正,我一定改

 

相關文章