java的三種工廠模式
阿新 • • 發佈:2018-12-16
工廠模式是用工廠方法代替了new操作, 將選擇實現類
, 建立物件
統一管理和控制.從而將呼叫者(Client)與實現類進行解耦.實現了建立者與呼叫者分離
;
java中的工廠模式又有三種模式,分別是靜態工廠、工廠模式和抽象模式。
使用場景:
- JDK中Calendar的getInstance方法;
- JDBC中Connection物件的獲取;
- MyBatis中SqlSessionFactory建立SqlSession;
- SpringIoC容器建立並管理Bean物件;
- 反射Class物件的newInstance;
- ….
一、靜態工廠
靜態工廠模式是工廠模式中最簡單的一種,他可以用比較簡單的方式隱藏建立物件的細節,一般只需要告訴工廠類所需要的型別,工廠類就會返回需要的產品類,而客戶端看到的也只是產品的抽象物件(interface),因此無需關心到底是返回了哪個子類
1、介面類
實現一個產品工廠,有兩種產品分別是A、B,使用靜態工廠完成產品的資訊輸出。
在介面中定義方法描述每種產品的資訊
package com.lq.demo;
public interface IProduct {
//描述每種產品的資訊
public void desc();
}
2、產品A
重寫介面的方法,實現產品A的資訊輸出
package com.lq.demo; public class ProductA implements IProduct{ @Override public void desc() { System.out.println("產品A的編號是001,名稱是A,最大金額是10000"); } }
3、產品B
重寫介面的方法,實現產品B的資訊輸出
package com.lq.demo;
public class ProductB implements IProduct{
@Override
public void desc() {
System.out.println("產品B的編號是002,名稱是B,最大金額是20000");
}
}
4.產品工廠
在工廠中定義產品型別,通過傳入的值判斷具體的產品
package com.lq.demo; public class ProductFactory { public static int type_A = 1;//產品A public static int type_B = 2;//產品B public static IProduct createProduct(int type){ switch(type){ case 1: return new ProductA(); case 2: default: return new ProductB(); } } }
5.測試類
package com.lq.test;
import com.lq.demo.IProduct;
import com.lq.demo.ProductFactory;
public class TestProduct {
public static void main(String[] args) {
//選擇了產品A
IProduct p = ProductFactory.createProduct(ProductFactory.type_A);
p.desc();
}
}
測試結果:
-
優點
- 隱藏了物件建立的細節,將產品的例項化過程放到了工廠中實現。
- 客戶端基本不用關心使用的是哪個產品,只需要知道用工廠的那個方法(或傳入什麼引數)就行了.
- 方便新增新的產品子類,每次只需要修改工廠類傳遞的型別值就行了。
- 遵循了
依賴倒轉
原則。
-
缺點
- 適用於產品子型別差不多, 使用的方法名都相同的情況.
- 每新增一個產品子類,都必須在工廠類中新增一個判斷分支(或一個方法),這違背了
OCP(開放-封閉原則)
。
二、工廠模式
工廠模式會提供一個用於建立物件的介面(工廠介面),讓其實現類(工廠實現類)決定例項化哪一個類(產品類),並且由該實現類建立對應類的例項。
提供一個產品類的介面。產品類均要實現這個介面(也可以是abstract類,即抽象產品)。 提供一個工廠類的介面。工廠類均要實現這個介面(即抽象工廠)。 由工廠實現類建立產品類的例項。工廠實現類應有一個方法,用來例項化產品類。
1、產品介面
實現產品的資訊輸出
package com.lq.demo;
public interface IProduct {
public void desc();
}
2、產品A
package com.lq.demo;
public class ProductA implements IProduct{
@Override
public void desc() {
System.out.println("產品型別是A,產品編號是001,最大金額是10000");
}
}
3、產品B
package com.lq.demo;
public class ProductB implements IProduct{
@Override
public void desc() {
System.out.println("產品型別是B,產品編號是002,最大金額是20000");
}
}
4、工廠介面
通過工廠介面建立工廠例項
package com.lq.demo;
public interface IProductFactory {
public IProduct createProduct(String type);
}
5、工廠例項
package com.lq.demo;
public class ProductFactory implements IProductFactory{
@Override
public IProduct createProduct(String type) {
IProduct product;
if(type.equals("A")){
product = new ProductA();
}else if(type.equals("B")){
product = new ProductB();
}else{
System.out.println("產品不存在,因此預設生產A");
product = new ProductA();
}
return product;
}
}
6、測試類
package com.lq.test;
import com.lq.demo.IProduct;
import com.lq.demo.IProductFactory;
import com.lq.demo.ProductFactory;
public class TestFactory {
public static void main(String[] args) {
//建立工廠
IProductFactory factory = new ProductFactory();
//通過工廠建立產品例項
IProduct product;
//建立產品A
product = factory.createProduct("A");
product.desc();
//建立產品B
product = factory.createProduct("B");
product.desc();
}
}
優點 基本與靜態工廠模式一致,多的一點優點就是遵循了開放-封閉原則,使得模式的靈活性更強。
缺點 與靜態工廠模式差不多, 但是增加了類組織的複雜性;
小結 雖然根據理論原則, 需要使用工廠方法模式, 但實際上, 常用的還是靜態工廠模式.
三、抽象工廠
抽象工廠模式: 提供一個建立一系列相關或相互依賴物件的介面, 而無需指定他們具體的類.
抽象工廠模式與工廠方法模式的區別:
- 抽象工廠模式是工廠方法模式的升級版本,他用來建立一組相關或者相互依賴的物件。他與工廠方法模式的區別就在於,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式則是針對的多個產品等級結構, 在程式設計中,通常一個產品結構,表現為一個介面或者抽象類,也就是說,工廠方法模式提供的所有產品都是衍生自同一個介面或抽象類,而抽象工廠模式所提供的產品則是衍生自不同的介面或抽象類
1、產品的編號介面
package com.lq.demo;
public interface IProductNumber {
public void getNumber();
}
class ProductANumber implements IProductNumber{
@Override
public void getNumber() {
System.out.println("產品編號是001");
}
}
class ProductBNumber implements IProductNumber{
@Override
public void getNumber() {
System.out.println("產品編號是002");
}
}
2、產品的名稱介面
package com.lq.demo;
public interface IProductName {
public void getName();
}
class ProductAName implements IProductName{
@Override
public void getName() {
System.out.println("產品名稱是A");
}
}
class ProductBName implements IProductName{
@Override
public void getName() {
System.out.println("產品名稱是B");
}
}
3、產品的金額介面
package com.lq.demo;
public interface IProductMoney {
public void getMax();
}
class ProductAMoney implements IProductMoney{
@Override
public void getMax() {
System.out.println("最大金額是10000");
}
}
class ProductBMoney implements IProductMoney{
@Override
public void getMax() {
System.out.println("最大金額是20000");
}
}
4、產品工廠
package com.lq.demo;
public interface IProduct {
public IProductNumber getNumber();
public IProductName getName();
public IProductMoney getMoney();
}
5、產品具體實現類A、B
package com.lq.demo;
public class ProductA implements IProduct{
@Override
public IProductNumber getNumber() {
return new ProductANumber();
}
@Override
public IProductName getName() {
return new ProductAName();
}
@Override
public IProductMoney getMoney() {
return new ProductAMoney();
}
}
package com.lq.demo;
public class ProductB implements IProduct{
@Override
public IProductNumber getNumber() {
return new ProductBNumber();
}
@Override
public IProductName getName() {
return new ProductBName();
}
@Override
public IProductMoney getMoney() {
return new ProductBMoney();
}
}
6、測試
package com.lq.test;
import com.lq.demo.IProduct;
import com.lq.demo.ProductA;
public class TestProduct {
public static void main(String[] args) {
//例項化產品A
IProduct A = new ProductA();
A.getNumber().getNumber();;
A.getName().getName();;
A.getMoney().getMax();;
}
}
結果:
- 優點
- 封裝了產品的建立,使得不需要知道具體是哪種產品,只需要知道是哪個工廠就行了。
- 可以支援不同型別的產品,使得模式靈活性更強。
- 可以非常方便的使用一族中間的不同型別的產品。
- 缺點
- 結構太過臃腫,如果產品型別比較多,或者產品族類比較多,就會非常難於管理。
- 每次如果新增一組產品,那麼所有的工廠類都必須新增一個方法,這樣違背了開放-封閉原則。所以一般適用於產品組合產品族變化不大的情況。
參考部落格: