1.簡單工廠模式
假如要設計一個類,根據用戶輸入參數的不同,產生不同的對象。
那么可以這樣寫:
public class Chart{
private String type;
public Chart{Object[][] data,String type){
this.type=type;
if(type.equalsIgnoreCase("aaa")){
// 第一種類型
}else if(type.equalsIgnoreCase("bbb")){
// 第二種類型
}else if(type.equalsIgnoreCase("ccc")){
// 第三種類型
}
}
public void display(){
if(this.type.equalsIgnoreCase("aaa")){
}else if (this.type.equalsIgnoreCase("bbb")){
}else if (this.type.equalsIgnoreCase("ccc")){
}
}
}
以上代碼的缺點
1.過多的if else 使得代碼很冗余
2.Chart類的職責過重,違反了單一原則
3.需要增加新的type時 需要更改代碼,違反開閉原則
4.與使用者耦合度太高
5.每種type的chart都需要進行初始化,代碼重復
這種情況下可以使用簡單工廠模式:
簡單工廠模式 又稱 靜態工廠模式
定義一個工廠類,根據參數的不同返回不同的 產品實例 ,產品實例有著共同的父類,即抽象的產品類。
要點:
傳入一個正確的參數就可以獲得一個對應的產品,而且無需知道創建細節。
修改后的代碼 可以這么寫:
abstract class Chart{
abstract void methodDiff();//每個type的chart的特有方法
public void methodSame(){ //所有type的chart的相同方法
}
}
class ChartA extends Chart{ //具體的chartA
public void methodDiff(){
}
}
class ChartB extends Chart{ //具體的chartB
public void methodDiff(){
}
}
class ChartFactory{
public static Chart getChart(String type){
Chart chart=null;
if(type.equalsIgnoreCase(“aaa”)){
chart=new ChartA();
}else if(type.equalsIgnoreCase("bbb")){
chart=new ChartB();
}
return chart;
}
}
// 客戶端獲取產品時 直接調用
Chart chart=ChartFactory.getChart("aaa");
總結
將對象的創建和使用分離
優點
1.對象的創建 和 使用分離
2.用戶不需要知道創建的具體對象
3.可以引入配置文件,可以在不改變代碼的情況下,添加或更換新的產品類
缺點
工廠類職責過重,產品類過多是會導致工廠類過于復雜。
違反開閉原則。
使用場景
產品類不多
客戶端并不關心產品類如何創建
2.工廠方法模式
interface Product{
public void Method();
}
class ProductA implements Product{
public void Method(){
//產品A
}
}
class ProductB implements Product{
public void Method(){
//產品B
}
}
// 若A B產品初始化都需要 經歷復雜的初始化
class ProductFactory{
public static Product getProduct(String type){
Product p=null;
if(type.equals("a")){
// 消耗大量資源的操作
p=new ProductA();
}else {
// 消耗大量資源的操作
p=new ProductB();
}
return p;
}
}
// 大量操作寫到構造方法中就不合適
此時可以使用 工廠方法模式。
又名 虛擬構造器模式(Virtual Constructor Pattern)或多態工廠模式(Polymorphic Factory Pattern),定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。
interface Factory {
public Product getProduct();
}
class AFactory implements Factory {
public Product getProduct(){
// 消耗大量資源的操作
return new ProductA();//亦可以 不返回對象,直接在此調用Method()方法,即對使用者隱藏了工廠方法 即隱藏了具體的對象。也可以通過配置文件寫入類名的方法,在此解析配置文件加載類名 然后反射產生對象
}
}
class BFactory implements Factory {
public Product getProduct(){ //亦可以弄幾個多態方法,來生成產品
// 消耗大量資源的操作
return new ProductB();
}
}
工廠方法模式的總結:
優點
1. 有新產品時,只需添加新的產品類和工廠類,無需修改之前的代碼 符合 開閉原則
2. 工廠類 和 產品類 都可以進行多態設計, 工廠可以自己確定創建哪個產品
3. 可以向調用者隱藏具體產品類,用戶不知道到底創建了哪一個產品類。用戶只關心對應的工廠,
缺點
- 需要引入抽象層,用戶均使用抽象層的定義
- 在添加新產品時,需要編寫新的具體產品類,而且還要提供與之對應的具體工廠類
3.抽象工廠模式
工廠方法模式 的情況下,每個工廠只生成一種產品。但是假如一個工廠要生成n種產品,而且有很多工廠時,那么 工廠方法模式 便不再合適。
此時可以使用抽象工廠方法。
若有 m個工廠,每個工廠都會生成相同的n種產品 。若按照一個工廠一種產品的想法,則需 m*n個工廠。
m個工廠,每個工廠稱為一個產品族。
n種產品,稱為n個產品等級。
抽象工廠方法的思路是:
AbstractFactory 定義生成這n種產品的方法,
| ProductA createProductA();
| ProductB createProductB();
| ProductC createProductC();
AbstractProduct 抽象的產品
ConcreteFactoryA extends AbstractFactory 具體工廠A
| ProductA createProductA();
| ProductB createProductB();
| ProductC createProductC();
ConcreteFactoryB extends AbstractFactory 具體工廠B
| ProductA createProductA();
| ProductB createProductB();
| ProductC createProductC();
即 定義m個工廠,均繼承自抽象工廠,所以實現了構造各種產品的方法,產生了這n中產品等級的所有產品。這種寫法,則需 m個工廠。
總結:
優點 :
- 抽象工廠模式隔離了具體類的生成,改變工廠類很容易。
- 保證客戶端使用的是同一個產品族的對象,即同一個工廠的產品
- 增加新的產品族非常容易, 符合開閉原則
缺點:
增加新產品不方便,不符合開閉原則