設計模式(四)——簡單工廠模式
設計模式(一)——設計模式概述 中簡單介紹了設計模式以及各種設計模式的基本概念,本文主要介紹簡單工廠模式,包括其概念、用途、實現方式及存在的問題等。
概念
簡單工廠模式是屬于創建型模式,又叫做靜態工廠方法(Static Factory Method)模式。簡單工廠模式是由一個工廠對象決定創建出哪一種產品類的實例。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以理解為是不同工廠模式的一個特殊實現。
值得注意的是,簡單工廠模式并不屬于23種GOF設計模式之一。但是他是抽象工廠模式,工廠方法模式的基礎,并且也有廣泛的應用。
用途
在介紹簡單工廠模式之前,我們嘗試解決以下問題:
現在我們要使用面向對象的形式定義計算器,為了實現各算法之間的解耦。主要的用到的類如下:
// 計算類的基類
public abstract class Operation {
private double value1 = 0;
private double value2 = 0;
public double getValue1() {
return value1;
}
public void setValue1(double value1) {
this.value1 = value1;
}
public double getValue2() {
return value2;
}
public void setValue2(double value2) {
this.value2 = value2;
}
protected abstract double getResule();
}
//加法
public class OperationAdd extends Operation {
@Override
protected double getResule() {
return getValue1() + getValue2();
}
}
//減法
public class OperationSub extends Operation {
@Override
protected double getResule() {
return getValue1() - getValue2();
}
}
//乘法
public class OperationMul extends Operation {
@Override
protected double getResule() {
return getValue1() * getValue2();
}
}
//除法
public class OperationDiv extends Operation {
@Override
protected double getResule() {
if (getValue2() != 0) {
return getValue1() / getValue2();
}
throw new IllegalArgumentException("除數不能為零");
}
}
當我想要執行加法運算時,可以使用如下代碼:
public class Main {
public static void main(String[] args) {
OperationAdd operationAdd = new OperationAdd();
operationAdd.setValue1(10);
operationAdd.setValue2(5);
System.out.println(operationAdd.getResule());
}
}
當我需要執行減法運算時,我就要創建一個OperationSub類。也就是說,我想要使用不同的運算的時候就要創建不同的類,并且要明確知道該類的名字。那么這種重復的創建類的工作其實可以放到一個統一的工廠類中。
簡單工廠模式有以下優點:
1、一個調用者想創建一個對象,只要知道其名稱就可以了。
2、屏蔽產品的具體實現,調用者只關心產品的接口。
實現方式
簡單工廠模式其實和他的名字一樣,很簡單。先來看看它的組成:
1) 工廠類角色:這是本模式的核心,含有一定的商業邏輯和判斷邏輯。在java中它往往由 一個具體類實現。(OperationFactory)
2) 抽象產品角色:它一般是具體產品繼承的父類或者實現的接口。在java中由接口或者抽象類來實現。(Operation)
3) 具體產品角色:工廠類所創建的對象就是此角色的實例。在java中由一個具體類實現。 來用類圖來清晰的表示下的它們之間的關系(OperationAdd\OperationSub等)
在原有類的基礎上,定義工廠類:
//工廠類
public class OperationFactory {
public static Operation createOperation(String operation) {
Operation oper = null;
switch (operation) {
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
case "*":
oper = new OperationMul();
break;
case "/":
oper = new OperationDiv();
break;
default:
throw new UnsupportedOperationException("不支持該操作");
break;
}
return oper;
}
}
有了工廠類之后,可以使用工廠創建對象:
Operation operationAdd = OperationFactory.createOperation("+");
operationAdd.setValue1(10);
operationAdd.setValue2(5);
System.out.println(operationAdd.getResule());
通過簡單工廠模式,該計算器的使用者不需要關系實現加法邏輯的那個類的具體名字,他只要知道該類對應的參數”+”就可以了。
簡單工廠模式存在的問題
在設計模式(一)——設計模式概述 中介紹了設計模式一般應該遵循的幾個原則。
下面我們從開閉原則(對擴展開放;對修改封閉)上來分析下簡單工廠模式。當我們需要增加一種計算時,例如開平方。這個時候我們需要先定義一個類繼承 Operation 類,其中實現平方的代碼。除此之外我們還要修改 OperationFactory 類的代碼,增加一個case。這顯然是違背開閉原則的。可想而知對于新產品的加入,工廠類是很被動的。
我們舉的例子是最簡單的情況。而在實際應用中,很可能產品是一個多層次的樹狀結構。 簡單工廠可能就不太適用了。
總結
工廠類是整個簡單工廠模式的關鍵。包含了必要的邏輯判斷,根據外界給定的信息,決定究竟應該創建哪個具體類的對象。通過使用工廠類,外界可以從直接創建具體產品對象的尷尬局面擺脫出來,僅僅需要負責“消費”對象就可以了。而不必管這些對象究竟如何創建及如何組織的。明確了各自的職責和權利,有利于整個軟件體系結構的優化。
但是
由于工廠類集中了所有實例的創建邏輯,違反了高內聚責任分配原則,將全部創建邏輯集中到了一個工廠類中;它所能創建的類只能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類了。
當系統中的具體產品類不斷增多時候,可能會出現要求工廠類根據不同條件創建不同實例的需求.這種對條件的判斷和對具體產品類型的判斷交錯在一起,很難避免模塊功能的蔓延,對系統的維護和擴展非常不利;
這些缺點在工廠方法模式中得到了一定的解決。
文中所有代碼見 GitHub