設計模式(一)之深入分析工廠設計模式

簡單工廠設計模式(Simple Factory Pattern)

指的是由一個工廠對象來決定創建出哪一類產品種類的實例.

簡單工廠示例

創建一個工廠接口:

package com.zwx.service;

public interface IFactory {
	public void create();
}

創建一個產品接口:

package com.zwx.service;

public interface IProduct {
	public void test();
}

創建產品A:

package com.zwx.service.impl;

import com.zwx.service.IProduct;

public class ProductA implements IProduct {
	public void test() {
		System.out.println("===test==ProductA===");
	}
}

創建產品B:

package com.zwx.service.impl;

import com.zwx.service.IProduct;

public class ProductB implements IProduct {
	public void test() {
		System.out.println("===test==ProductB===");
	}
}

工廠實現類,實現了創建對象具體方法

package com.zwx.service.impl;

import com.zwx.service.IProduct;

public class SimpleFactory{
	public IProduct create(String name){
		if("A".equals(name)){
			return new ProductA();
		}else if("B".equals(name)){
			return new ProductB();
		}
		return null;
	}

測試類

package com.zwx.controller;

import com.zwx.service.IProduct;
import com.zwx.service.impl.SimpleFactory;

public class TestFactory1 {
	public static void main(String[] args) {
		SimpleFactory simpleFactory = new SimpleFactory();
		IProduct procuct = simpleFactory.create("A");
		procuct.test();
	}
}

上面就基本上實現了一個簡單工廠模式,但是我們發現,假如我們要增加一個產品C,那麼我們就需要去修改創建工廠實現了類,這就違背了軟件設計的開閉原則,所以,我們可以對CreateFactory類利用反射進行改進。
改進後的工廠實現類

package com.zwx.service.impl;

import com.zwx.service.IProduct;

public class SimpleFactory {
	public IProduct create2(Class<? extends IProduct> clazz) throws InstantiationException, IllegalAccessException{
		if(null == clazz){
			return null;
		}
		return clazz.newInstance();
	}
}

測試類:

package com.zwx.controller;

import com.zwx.service.IFactoryMethod;
import com.zwx.service.IProduct;
import com.zwx.service.impl.ProductCCFactory;
import com.zwx.service.impl.ProductCFactory;

/**
 * 工廠方法測試
 * @author zwx
 */
public class TestFactory2 {
	public static void main(String[] args) {
//		IFactoryMethod factory = new ProductCFactory();
//		IProduct product = factory.create();
//		product.test();
		
		IFactoryMethod factory2 = new ProductCCFactory();
		IProduct product2 = factory2.create();
		product2.test();
	}
}

簡單工廠模式適用場景

簡單工廠適用於工廠類負責創建的對象較少的場景,且客戶端只需要傳入工廠類的參數,對於如何創建對象的邏輯不需要關心

簡單工廠模式缺點

假如每種產品創建不僅僅只是實例化一個對象,還有其他邏輯需要處理,那麼我們無法直接使用一句反射,避免不了寫很多if(亦或者用switch循環),這樣的話每新增一個產品我們都需要修改工廠實現類,隨着產品鏈越來越豐富,工廠的職責會變得越來越多,久而久之會越來越難以維護。

工廠方法設計模式(Fatory Method Pattern)

工廠方法模式是指定義一個創建對象的接口,但讓實現這個接口的類來決定實例化哪個對象,工廠方法讓類的實例化推遲到子類中進行,在工廠方法模式中用戶只需要關心所需產品對應的工廠,無須關心創建細節,而且加入新的產品符合開閉原則。

創建一個工廠接口,注意這裏和簡單工廠的區別是接口內方法有返回值

package com.zwx.service;
public interface IFactoryMethod {
	public IFactoryMethod create();
}

創建一個產品C類

package com.zwx.service.impl;

import com.zwx.service.IProduct;

public class ProductC implements IProduct {
	public void test(){
		System.out.println("===test==ProductC===");
	}
}

創建一個產品C工廠類

package com.zwx.service.impl;

import com.zwx.service.IFactoryMethod;
import com.zwx.service.IProduct;

public class ProductCFactory implements IFactoryMethod {
	public IProduct create() {
		return new ProductC();
	}
}

最後,添加測試類

package com.zwx.controller;

import com.zwx.service.IFactoryMethod;
import com.zwx.service.IProduct;
import com.zwx.service.impl.ProductCFactory;

public class TestFactory2 {
	public static void main(String[] args) {
		IFactoryMethod factory = new ProductCFactory();
		IProduct product = factory.create();
		product.test();
	}
}

如此就成功創建了對象C,假如要增加對象D,那麼我們只需要新增一個對象C類和其對應的一個工廠類即可,不需要去修改原有的工廠類,符合了開閉原則。

工廠方法模式適用場景

1、創建對象需要大量重複的代碼。
2、客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節。
3、一個類通過其子類來指定創建哪個對象。

工廠方法模式缺點

1、類的個數容易過多,增加複雜度。
2、增加了系統的抽象性和理解難度

抽象工廠模式(Abstract Factory Pattern)

抽象工廠模式是指提供一個創建一系列相關或相互依賴對象的接口,無須指定他們具體的類。客戶端(應用層)不依賴於產品類實例如何被創建、實現等細節,強調的是一系列相關的產品對象(屬於同一產品族)一起使用創建對象需要大量重複的代碼。需要提供一個產品類的庫,所有的產品以同樣的接口出現,從而使客戶端不依賴於具體實現。

抽象工廠示例

創建一個抽象接口:

package com.zwx.service;

public interface IAbstractFactory {
	IApple createApple();
	IOrange createOrange();
}

創建兩個產品接口:

package com.zwx.service;

public interface IApple {
	void eatApple();
}
package com.zwx.service;

public interface IOrange {
	void eatOrange();
}

假設現在有一個農場要去生產這兩種產品,建立如下兩個類:

package com.zwx.service.impl;

import com.zwx.service.IApple;

public class Farm1Apple implements IApple {
	public void testApple() {
		System.out.println("=====farm1==testApple");
	}
}
package com.zwx.service.impl;

import com.zwx.service.IOrange;

public class Farm1Orange implements IOrange{
	public void testOrange() {
		System.out.println("=====farm1==testOrange");
	}
}

接下來創建一個農場1的具體工廠類:

package com.zwx.service.impl;

import com.zwx.service.IAbstractFactory;
import com.zwx.service.IApple;
import com.zwx.service.IOrange;

public class Farm1AbstractFactory implements IAbstractFactory{

	public IApple createApple() {
		return new Farm1Apple();
	}

	public IOrange createOrange() {
		return new Farm1Orange();
	}
}

最後再建立一個測試類測試:

package com.zwx.controller;

import com.zwx.service.impl.Farm1AbstractFactory;

public class TestFactory3 {
	public static void main(String[] args) {
		Farm1AbstractFactory factory = new Farm1AbstractFactory();
		factory.createApple().testApple();
		factory.createOrange().testOrange();
	}
}

此時,如果有一個農場2又要來生產Apple和Orange,那麼再新增兩個對應的產品類以及一個具體工廠類即可實現。

抽象工廠使用場景

當我們有一系列產品(如上面的Apple,Orange)。而這一系列產品每種產品又需要具有不同的創建方法(如上種植Apple和種植Orange方法肯定是不同的需要不同的方法實現)。

抽象工廠缺點

1、規定了所有可能被創建的產品集合,產品族中擴展新的產品困難,需要修改抽象工廠
的接口。
2、增加了系統的抽象性和理解難度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章