工廠模式(簡單工廠、工廠方法、抽象工廠)
簡單工廠模式
定義
簡單工廠模式又稱靜態工廠方法模式,它是由一個工廠角色統一建立不同的物件,但這些物件都繼承自同一個類。
結構
1.工廠角色:根據傳入不同的引數,例項化對應的具體類。
2.具體角色:工廠類返回的物件,它們繼承自同一個父類。
3.父類:它是所有具體角色的父類,定義了所有公共介面
類圖
案例
以實現一個計算器介面為例。
父類
package com.headfirst.simplefactorypattern.dao; public class Calculator { double numA = 0; double numB = 0; public double getResult(){ return 0.0; } }
工廠類
package com.headfirst.simplefactorypattern.dao; public class CalculatorFactory { public static Calculator cal = null; public static Calculator createFactory(String operate){ switch (operate) { case "+": if(cal == null){ cal = new plus(); } break; case "-": if(cal == null){ cal = new sub(); } break; case "*": if(cal == null){ cal = new mul(); } break; case "/": if(cal == null){ cal = new div(); } break; } return cal; } }
具體實現類
加法
package com.headfirst.simplefactorypattern.dao;
public class plus extends Calculator{
public double getResult(){
return numA + numB;
}
}
減法
package com.headfirst.simplefactorypattern.dao; public class sub extends Calculator{ public double getResult(){ return numA - numB; } }
乘法
package com.headfirst.simplefactorypattern.dao;
public class mul extends Calculator{
public double getResult(){
return numA * numB;
}
}
除法
package com.headfirst.simplefactorypattern.dao;
public class div extends Calculator{
public double getResult(){
return numA / numB;
}
}
測試類
public static void main(String[] args) {
Calculator factory = CalculatorFactory.createFactory("/");
factory.numA = 26;
factory.numB = 2.5;
System.out.println(factory.getResult());
}
優點
1.實現使用和建立的分離
2.客戶端不需要知道具體實現類的類名,只需要知道對應的引數即可建立物件
缺點
1.當需要新增一個具體類時,需要修改工廠類的程式碼邏輯,違背了OCP(開放-封閉原則)
2.由於工廠類中建立物件的方法是靜態的,無法被繼承實現
工廠方法模式
定義
工廠方法模式定義了一個用於建立物件的介面,讓子類決定例項化那一個類,工廠方法是一個類的例項化延遲到其子類。
類圖
工廠方法模式解決的問題
由於簡單工廠模式違背了OCP開放-封閉原則,對修改封閉,所以在這裡簡單工廠的switch-case邏輯判斷不存在了,每個具體實現類對應一個子類工廠,這些子類工廠都繼承自抽象工廠介面。
當需要新增一個功能,只需要新增一個具體實現類和一個子類工廠即可。
案例
我還以實現一個計算器程式為例,這裡省去具體實現類的程式碼。
工廠類介面
package com.headfirst.factorymethodmode.interfaces;
import com.headfirst.simplefactorypattern.dao.Calculator;
public interface ICalculatorFactory {
public Calculator createFactory();
}
加法工廠類
package com.headfirst.factorymethodmode.dao;
import com.headfirst.factorymethodmode.interfaces.ICalculatorFactory;
import com.headfirst.simplefactorypattern.dao.Calculator;
import com.headfirst.simplefactorypattern.dao.plus;
public class addFactory implements ICalculatorFactory{
@Override
public Calculator createFactory() {
Calculator cal = new plus();
return cal;
}
}
減法工廠類
package com.headfirst.factorymethodmode.dao;
import com.headfirst.factorymethodmode.interfaces.ICalculatorFactory;
import com.headfirst.simplefactorypattern.dao.Calculator;
import com.headfirst.simplefactorypattern.dao.sub;
public class subFactory implements ICalculatorFactory{
@Override
public Calculator createFactory() {
Calculator cal = new sub();
return cal;
}
}
乘法工廠類
package com.headfirst.factorymethodmode.dao;
import com.headfirst.factorymethodmode.interfaces.ICalculatorFactory;
import com.headfirst.simplefactorypattern.dao.Calculator;
import com.headfirst.simplefactorypattern.dao.mul;
public class mulFactory implements ICalculatorFactory{
@Override
public Calculator createFactory() {
Calculator cal = new mul();
return cal;
}
}
除法工廠類
package com.headfirst.factorymethodmode.dao;
import com.headfirst.factorymethodmode.interfaces.ICalculatorFactory;
import com.headfirst.simplefactorypattern.dao.Calculator;
import com.headfirst.simplefactorypattern.dao.div;
public class divFactory implements ICalculatorFactory{
@Override
public Calculator createFactory() {
Calculator cal = new div();
return cal;
}
}
測試類
public static void main(String[] args) {
divFactory factory = new divFactory();
Calculator cal = factory.createFactory();
cal.setNumA(2.5);
cal.setNumB(5.0);
System.out.println(cal.getResult());
}
優點
實現使用和建立的分離。
缺點
每增加一個具體實現類就要對應增加一個子類工廠,增加了工作量。
抽象工廠模式
定義
抽象工廠模式是提供建立一系列相關或相互依賴物件的介面,而無需指定具體的類。
結構
1.抽象工廠介面(abstractfactory):相當於一個超級工廠,它是工廠的工廠,它包含了所有產品建立的方法,在這裡是抽象方法。
2.具體工廠(concretefactory):建立具有特定實現的產品物件,多個具體工廠跟抽象產品的具體實現類對應。
3.抽象產品(abstractproduct):定義了該產品的一系列介面,多個抽象產品的方法都彙總在抽象工廠介面中。
4.具體實現類(product):一個具體實現類對應一個具體工廠,一個具體工廠可以對應多個具體實現類。
類圖
案例
以讀寫User物件和department物件需要同時實現oracle資料庫讀寫和mysql資料庫讀寫為例(user類和department類的程式碼這裡沒有貼出來)
產品A:IUser(介面)
package com.headfirst.abstractfactorymode.interfaces;
import com.headfirst.abstractfactorymode.dao.User;
public interface IUser {
void insertUser(User user);
User getUser();
}
產品B:IDepartment(介面)
package com.headfirst.abstractfactorymode.interfaces;
import com.headfirst.abstractfactorymode.dao.Department;
public interface IDepartment {
void insertDepartment(Department department);
Department getDepartment();
}
oracle讀寫user物件的具體實現類:OracleUser
package com.headfirst.abstractfactorymode.dao;
import com.headfirst.abstractfactorymode.interfaces.IUser;
public class OracleUser implements IUser {
@Override
public void insertUser(User user) {
System.out.println("向oracle中插入一條User物件");
}
@Override
public User getUser() {
System.out.println("從oracle中查詢User物件");
return null;
}
}
oracle讀寫department物件的具體實現類:OracleDepartment
package com.headfirst.abstractfactorymode.dao;
import com.headfirst.abstractfactorymode.interfaces.IDepartment;
public class OracleDepartment implements IDepartment {
@Override
public void insertDepartment(Department department) {
System.out.println("向oracle中插入一條department物件");
}
@Override
public Department getDepartment() {
System.out.println("從oracle中查詢department物件");
return null;
}
}
mysql讀寫user物件的具體實現類:MysqlUser
package com.headfirst.abstractfactorymode.dao;
import com.headfirst.abstractfactorymode.interfaces.IUser;
public class MysqlUser implements IUser {
@Override
public void insertUser(User user) {
System.out.println("向mysql中插入一條User物件");
}
@Override
public User getUser() {
System.out.println("從mysql中查詢User物件");
return null;
}
}
mysql讀寫department物件的具體實現類:MySQLDepartment
package com.headfirst.abstractfactorymode.dao;
import com.headfirst.abstractfactorymode.interfaces.IDepartment;
public class MySQLDepartment implements IDepartment {
@Override
public void insertDepartment(Department department) {
System.out.println("向mysql中插入一條department物件");
}
@Override
public Department getDepartment() {
System.out.println("從mysql中查詢department物件");
return null;
}
}
抽象工廠介面:IFactory
package com.headfirst.abstractfactorymode.interfaces;
import com.headfirst.abstractfactorymode.dao.Department;
import com.headfirst.abstractfactorymode.dao.User;
public interface IFactory {
IUser createUser();
IDepartment createideDepartment();
}
Oracle讀寫物件的具體工廠:OracleFactory
package com.headfirst.abstractfactorymode.dao;
import com.headfirst.abstractfactorymode.interfaces.IDepartment;
import com.headfirst.abstractfactorymode.interfaces.IFactory;
import com.headfirst.abstractfactorymode.interfaces.IUser;
public class OracleFactory implements IFactory {
@Override
public IUser createUser() {
return new OracleUser();
}
@Override
public IDepartment createideDepartment() {
return new OracleDepartment();
}
}
mysql讀寫物件的具體工廠:MysqlFactory
package com.headfirst.abstractfactorymode.dao;
import com.headfirst.abstractfactorymode.interfaces.IDepartment;
import com.headfirst.abstractfactorymode.interfaces.IFactory;
import com.headfirst.abstractfactorymode.interfaces.IUser;
public class MysqlFactory implements IFactory {
@Override
public IUser createUser() {
return new MysqlUser();
}
@Override
public IDepartment createideDepartment() {
return new MySQLDepartment();
}
}
測試類:
public static void main(String[] args) {
OracleFactory oracleFactory = new OracleFactory();
IUser iUser = oracleFactory.createUser();
iUser.insertUser(new User());
iUser.getUser();
IDepartment iDepartment = oracleFactory.createideDepartment();
iDepartment.insertDepartment(new Department());
iDepartment.getDepartment();
MysqlFactory mysqlFactory = new MysqlFactory();
IUser iUser2 = mysqlFactory.createUser();
iUser2.insertUser(new User());
iUser2.getUser();
IDepartment iDepartment2 = mysqlFactory.createideDepartment();
iDepartment2.insertDepartment(new Department());
iDepartment2.getDepartment();
}
測試結果:
優點
靈活地交換產品,保證產品族中使用同一個產品,例如資料庫要麼全部使用oracle,要麼全部使用mysql
缺點
當增加一個新的產品時,維護起來很困難,例如新加一個sqlserver,需要新增一套支援sqlserver的具體實現類和具體工廠。