菜鳥成長系列-工廠模式

菜鳥成長系列-概述
菜鳥成長系列-面向對象的四大基礎特性
菜鳥成長系列-多態、接口和抽象類
菜鳥成長系列-面向對象的6種設計原則
菜鳥成長系列-單例模式java

上一篇咱們已經對建立型模式中的單例模式進行了學習,今天來學習另一個比較重要而且常用的模式-工廠模式;工廠模式專門負責將大量有共同接口的類實例化。其能夠動態的決定將哪個類實例化,沒必要事先知道每次要實例化哪個類。bash

工廠模式具備如下三種形態:架構

  • 簡單工廠模式:又稱靜態工廠模式
  • 工廠方法模式:又稱多態性工廠模式或者虛擬構造子模式
  • 抽象工廠模式:又稱工具箱模式

本篇文章將對這三種形態的工廠模式進行一些基本的學習,並經過例子來直觀的感覺下不一樣形態的具體實現方式。最後再分析下JAVA以及Spring中是如何使用的。app

一、簡單工廠模式

從上圖能夠看出,簡單工廠模式涉及到工廠角色、抽象產品角色以及具體產品角色等三個角色。各角色職能以下:

  • 工廠類:擔任這個角色的是工廠方法模式的核心,含有與應用緊密相關的具體業務邏輯。工廠類在客戶端的直接調用下建立產品對象,它每每由一個具體的java類實現
  • 抽象產品:擔任這個角色的類是工廠方法模式所建立的對象的父類,或它們共同擁有的接口。抽象產品角色能夠用一個java接口或者抽象類來實現
  • 具體產品:工廠方法模式所建立的任何對象都是這個角色的實例,具體產品角色由一個java類實現

來看例子,考慮到今天有小夥伴來我這作客,本demo將以作菜來實現一波。首先工廠就是廚房,抽象類就是籠統的菜,實現類就是具體哪一個菜。

  • 抽象產品
package com.glmapper.design.factory;
/**
 * 抽象類角色:food接口,約束類型
 * @author glmapper
 * @date 2017年12月24日上午10:38:36
 *
 */
public interface IFood {
	/**
	 * 提供一個展現食物細節的方法
	 * @param foodName 食物名稱
	 */
	public void showFood();
}

複製代碼
  • 具體產品-魚
package com.glmapper.design.factory;
/**
 * 具體產品-食物魚
 * @author glmapper
 * @date 2017年12月24日上午10:51:29
 *
 */
public class FishFood implements IFood
{
	@Override
	public void showFood() {
		System.out.println("一盤魚");
	}
}
複製代碼
  • 具體產品-土豆絲
package com.glmapper.design.factory;
/**
 * 
 * 具體食物:土豆絲
 * @author glmapper
 * @date 2017年12月24日上午10:47:17
 *
 */
public class ShreddedPotatoesFood implements IFood{
	@Override
	public void showFood() {
		System.out.println("一盤土豆絲");
		
	}
}
複製代碼
  • 工廠角色 - 食物工廠
package com.glmapper.design.factory;
/**
 * 工廠角色-食物工廠
 * 
 * @author glmapper
 * @date 2017年12月24日上午10:41:10
 *
 */
public class SimpleFoodFactory {
	/**
	 * 提供一個靜態方法,用於獲取食物
	 * @param foodType 食物類型
	 * @return 具體食物
	 */
	public static IFood getFood(String foodType){
		IFood food = null;
		if (foodType.equals("fish")) {
			food = new FishFood();
		}
		if (foodType.equals("potatoes")) {
			food = new ShreddedPotatoesFood();
		}
		return food;
	}
}
複製代碼
  • 客戶端
package com.glmapper.design.factory;
/**
 * 客戶端
 * @author glmapper
 * @date 2017年12月24日上午10:45:17
 *
 */
public class MainTest {
	public static void main(String[] args) {
		IFood fishfood = SimpleFoodFactory.getFood("fish");
		fishfood.showFood();
		
		IFood potatoesfood = SimpleFoodFactory.getFood("potatoes");
		potatoesfood.showFood();
	}
}
複製代碼
  • 結果
一盤魚
一盤土豆絲
複製代碼

OK,菜作完了,能夠吃了。。。ide

咱們來討論下簡單工廠模式的優缺點:工具

優勢:模式的核心是工廠類,這個類含有必要的判斷邏輯,能夠決定在何時建立哪個產品類的實例。而客戶端則能夠免除直接建立產品對象的責任,而僅僅負責消費產品便可。用一句話來講就是:簡單工廠模式這個作法實現了對責任的分割。
缺點:集中了全部產品的建立邏輯,造成了一個無所不能的全職類,可是以前咱們在討論設計原則的時候說過,咱們要儘可能避免這種狀況的發生,這種就很明顯破壞了單一職責這條原則,另外也不知足開閉原則的約束。當咱們須要進行品類擴展時,咱們須要不斷的去修改咱們的工廠的業務邏輯,一方面是工廠類會急速的膨脹,另外一方面由於囊括了不一樣的產品對於咱們後期的維護形成必定的影響。源碼分析

二、工廠方法模式

這個時候一個同事說他是南方人,另一個同事說他是北方人,吃不慣今天的菜。post

好吧,既然這樣,那我就只能點外賣了。。。可是爲了防止他們變卦本身的家鄉,我須要作一個計劃,下面就是計劃圖:

從上圖中咱們能夠看出,工廠方法模式的角色包括如下幾種:學習

  • 抽象工廠:是工廠方法模式的核心,與應用程序無關。任何在模式中建立的對象的工廠類必須實現這個接口。
  • 具體工廠:這是實現抽象工廠接口的具體工廠類,包含與應用程序密切相關的邏輯,而且受到應用程序調用以建立產品對象。
  • 抽象產品:工廠方法模式所建立的對象的超類型,也就是產品對象的共同父類或共同擁有的接口
  • 具體產品:這個角色實現了抽象產品角色所定義的接口。某具體產品有專門的具體工廠建立,它們之間每每一一對應。

由於個人同事都是來自不一樣地方的,他們的口味也都不同,可是呢同事都是第一次來我家吃飯,因此爲了招待周全,根據同事不一樣的口味叫不一樣口味的魚。ui

  • 抽象工廠角色:獲取食物
package com.glmapper.design.factory;
/**
 * 
 * 角色1:抽象工廠 - 負責獲取食物
 * @author glmapper
 * @date 2017年12月24日下午1:59:28
 */
public interface MethodFoodFactory {
	//獲取食物的方法
	public IFishFood getFood();
}
複製代碼
  • 具體工廠1:獲取南方食物-魚
package com.glmapper.design.factory;
/**
 * 南方口味外賣 - 魚
 * @author glmapper
 * @date 2017年12月24日下午2:03:36
 */
public class SouthFishFactory implements MethodFoodFactory{
	@Override
	public IFishFood getFood() {
		return new SouthFishFood();
	}
}

複製代碼
  • 具體工廠2:獲取北方食物-魚
package com.glmapper.design.factory;
/**
 * 北方口味外賣 - 魚
 * @author glmapper
 * @date 2017年12月24日下午2:03:36
 */
public class NorthFishFactory implements MethodFoodFactory{

	@Override
	public IFishFood getFood() {
		// TODO Auto-generated method stub
		return new NorthFishFood();
	}
}
複製代碼
  • 具體產品1:南方食物- 魚
package com.glmapper.design.factory;
/**
 * 南方口味-魚
 * @author glmapper
 * @date 2017年12月24日下午2:16:17
 */
public class SouthFishFood implements IFishFood{
	@Override
	public void showFood() {
		System.out.println("來自南方廚師作的魚");
	}
}
複製代碼
  • 具體產品2:北方食物-魚
package com.glmapper.design.factory;
/**
 * 北方口味  - 魚
 * @author glmapper
 * @date 2017年12月24日下午2:12:55
 */
public class NorthFishFood implements IFishFood {
	@Override
	public void showFood() {
		System.out.println("來自北方廚師作的魚");
	}
}
複製代碼
  • 客戶端
package com.glmapper.design.factory;
/**
 * 客戶端
 * @author glmapper
 * @date 2017年12月24日上午10:45:17
 */
public class MainTest {
	public static void main(String[] args) {
		//點一個南方口味外賣
		MethodFoodFactory southFoodFactory = new SouthFishFactory();
		//點一個北方口味外賣
		MethodFoodFactory northFoodFactory = new NorthFishFactory();
		//拿到南方口味外賣魚
		southFoodFactory.getFood().showFood();
		//拿到北方口味外賣魚
		northFoodFactory.getFood().showFood();
	}
}
複製代碼
  • 結果:
來自南方廚師作的魚
來自北方廚師作的魚
複製代碼

OK,這樣咱們就知足了不一樣區域同時關於魚口味的需求了,之後升值加薪就期望他們了。。。

關於工廠方法模式的優缺點:

優勢:
一、 在工廠方法中,用戶只須要知道所要產品的具體工廠,無須關係具體的建立過程,甚至不須要具體產品類的類名。
二、 在系統增長新的產品時,咱們只須要添加一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了「開閉原則」
缺點:
每次增長一個產品時,都須要增長一個具體類和對象實現工廠,是的系統中類的個數成倍增長,在必定程度上增長了系統的複雜度,同時也增長了系統具體類的依賴。這並非什麼好事。

三、抽象工廠模式

準備吃飯的時候忽然又來了幾位同事,並且他們有的喜歡吃酸菜魚,有的喜歡吃紅燒魚,這就很頭疼。因而,只能根據他們的須要繼續點外賣。(這個就給出一個結構圖,而且將每種角色都用具體的場景來講明瞭,具體的代碼能夠參考這個圖例本身嘗試一下。)

OK,終於能夠吃飯了!

四、三種形態的工廠模式在java中的使用

4.一、簡單工廠模式在java中的使用

java.text.DateFormat (一個抽象類)這個類相信不少小夥伴都用到過,在java API中,這個類算是一個簡單工廠模式的典型應用了(此處仍是與上篇同樣,不考慮期源碼細節,也不介紹基本用法)。來看它的幾個方法:

  • public final static DateFormat getDateInstance()
  • public final static DateFormat getDateInstance(int style)
  • public final static DateFormat getDateInstance(int style, Locale aLocale)

做爲一個抽象類,卻提供了不少的靜態工廠方法,就像上面列舉的那三個同樣。有小夥伴可能會疑惑,爲啥子一個抽象類闊以有本身的實例,並經過幾個方法提供本身的實例。咱們知道,抽象類是不能夠有本身的實例對象的,可是須要注意的是,DateFormat的工廠方法是靜態的,並非普通的方法,也就是說,不須要經過建立實例對象的方式去調用。

public final static DateFormat getDateInstance()
{
    return get(0, DEFAULT, 2, Locale.getDefault(Locale.Category.FORMAT));
}
複製代碼

getDateInstance方法並無經過調用DateFormat的構造方法來建立對象。

4.二、工廠方法模式在java中的應用

java.net.URL類,類圖以下,

URL對象經過一個工廠方法openConnection()返回一個URLConnection類型的對象。URLConnection是一個抽象類,所以所返還的不多是這個抽象類的實例,而必然是其具體子類的實例。

4.三、抽象工廠模式在java中的應用

根據java與模式一書的介紹,在java中使用抽象工廠模式的是 JAVA awt的peer架構,經過抽象工廠模式來構建分屬於不一樣操做系統的peer構件。這個我也沒用過,瞭解便可。

關於Spring中工廠模式的使用會在後續Spring源碼分析系列中給你們詳細分析,這裏就不重複了。

今天的學習就到此結束了,祝你們週末愉快。話說今天平安夜,你們都是在家寫代碼嗎?

若是您對系列文章有任何意見,能夠給我留言,感謝你們。

下面是一個接蘋果的姿式,呼呼呼.....

相關文章
相關標籤/搜索