三大工廠設計模式對比
簡單工廠設計模式(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、增加了系統的抽象性和理解難度。