1. 程式人生 > >工廠模式(簡單工廠、工廠方法、抽象工廠)

工廠模式(簡單工廠、工廠方法、抽象工廠)

簡單工廠模式

定義

簡單工廠模式又稱靜態工廠方法模式,它是由一個工廠角色統一建立不同的物件,但這些物件都繼承自同一個類。

結構

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的具體實現類和具體工廠。