設計模式——工廠方法模式

leyan發表於2018-01-29

工廠方法模式

定義:Define an interface for creating an object, but let subclasses decide which class instance. Factory Method lets a class defer instantiation to subclasses.
(定義一個用於建立物件的介面 [這裡的介面一詞並不指Java中的介面構造,它可以是Java介面或抽象類] ,但是讓子類決定去例項化哪個類。工廠方法將物件的例項化推遲到其子類。)

優勢
[1].良好的封裝性,程式碼結構清晰。如果一個呼叫者需要一個具體的產品物件,只要知道這個產品的類名就可以了,不用關心物件是如何建立的,降低了模組見得耦合。
[2].工廠方法模式擴充套件性非常優秀。如果想增加一個產品類,只需要適當的修改具體的工廠類或擴充套件一個工廠類就可以完成。
[3].遮蔽品類。產品的實現如何變化,呼叫者都不需要關心,它只需要關心產品的介面,只要介面保持不變,系統中的上層模組就不需要發生變化。因為產品的例項化工作是由工廠類負責的,一個產品物件具體由哪一個產品生成是由工廠類決定的。 例如:在資料庫開發中,如果使用 JDBC 連線資料庫,資料庫從 MySQL 且款到 Oracle,只需要改動的地方就是切換一下驅動名稱。
[4].工廠方法模式是典型的解耦框架。高層模組值只需要知道產品的抽象類,其他的實現類都不用關心,符合迪米特法則,我不需要的就不要去交流;也符合依賴倒置原則,只依賴產品的抽象;也符合里氏替換原則,使用產品子類替換父類。


簡單工廠模式(Simple Factory Pattern)

基本組成
產品抽象類Product
具體產品類ConcreteProduct1 ConcreteProduct2
工廠類Creator
  • 產品抽象
public abstract class Product {
	public abstract void method();
}
複製程式碼

  • 具體產品
public class ConcreteProduct1 extends Product{
	@Override
	public void method() {
	    // do something...
	}
}
public class ConcreteProduct2 extends Product{
	@Override
	public void method() {
	    // do something...
	}
}
複製程式碼

  • 工廠(第一種實現方式)
public class Creator{
	public static <T extends Product> T createProduct(Class<T> c) {
		Product product=null;
		try {
			product=(Product)Class.forName(c.getName()).newInstance();
		}catch(Exception e) {
			// do something...
		}
		return (T)product;
	}
}
複製程式碼

特點:工廠是一個具體類,非抽象類 非介面,它的create方法,是利用反射機制生成物件返回,增加一種產品時,不需要修改工廠的程式碼。
缺點:不同的產品需要不同額外引數的時候 不支援。


  • 工廠(第二種實現方式)
public class Creator{
        public static final int PRODUCT_ONE = 1;
        public static final int PROCUCT_TWO = 2;
        
	public static Product createProduct(int type) {
		switch(type){
		    case PRODUCT_ONE:
		        return new ConcreteProduct1();
		    case PROCUCT_TWO:
		    default:
		        return new ConcreteProduct2();
		}
	}
}
複製程式碼

特點:工廠是一個具體類,非抽象類 非介面,create方法通常是靜態的,所以也稱之為靜態工廠。
缺點:擴充套件性差,當我們需要增加一個產品類時還需要修改工廠類; 不同的產品需要不同額外引數的時候 不支援。


多方法靜態工廠

簡單工廠模式的一個問題是 當產品需要不同額外引數的時候 不支援。 而且如果使用時傳遞的 typeClass 出錯,將不能得到正確的物件,容錯性不高。
而多方法的工廠模式為不同產品,提供不同的生產方法。

基本組成
產品抽象類Product
具體產品類ConcreteProduct1 ConcreteProduct2
工廠類Creator
  • 產品抽象
public abstract class Product {
	public abstract void method();
}
複製程式碼

  • 具體產品
public class ConcreteProduct1 extends Product{
    
    private String name;
    
    public ConcreteProduct1(String name){
        this.name = name;
    }

    @Override
    public void method() {
	    // do something...
    }
}

public class ConcreteProduct2 extends Product{

    private String name;
    private int size;
    
    public ConcreteProduct2(String name, int size){
        this.name = name;
        this.size = size;
    }

    @Override
    public void method() {
	    // do something...
    }
}
複製程式碼

  • 工廠
public class Creator{

    public static Procuct createProduct1(String name){
        return new ConcreteProduct1(name);
    }
    
    public static Procuct createProduct2(String name, int size){
        return new ConcreteProduct2(name, size);
    }
}
複製程式碼

優點:方便建立 同種型別的 複雜引數 物件


普通工廠

基本組成
產品抽象類Product
工廠抽象類Creator
具體產品類ConcreteProduct1 ConcreteProduct2
具體工廠類ConcreteCreator1 ConcreteCreator2
  • 產品抽象
public abstract class Product {
	public abstract void method();
}
複製程式碼

  • 工廠抽象
public abstract class Creator{
    public abstract Product create();
}
複製程式碼

  • 具體產品
public class ConcreteProduct1 extends Product{
	@Override
	public void method() {
	    // do something...
	}
}
public class ConcreteProduct2 extends Product{
	@Override
	public void method() {
	    // do something...
	}
}
複製程式碼

  • 具體工廠
public class ConcreteCreator1 extends Creator{
    @Override
    public Product create(){
        return new ConcreteCreator1();
    }
}
public class ConcreteCreator2 extends Creator{
    @Override
    public Product create(){
        return new ConcreteCreator2();
    }
}
複製程式碼

特點:不僅僅產品需要抽象, 工廠也需要抽象;工廠方法使一個產品類的例項化延遲到其具體工廠子類。
優點:擁抱變化,當需求變化,只需要增刪相應的類,不需要修改已有的類。而簡單工廠需要修改工廠類的create方法,多方法靜態工廠模式需要增加一個靜態方法。
缺點:引入抽象工廠層後,每次新增一個具體產品類,也要同時新增一個具體工廠類。

相關文章