23種設計模式(2)-工廠模式
定義:
工廠模式是 Java 中最常用的設計模式之一。這種型別的設計模式屬於建立型模式,它提供了一種建立物件的最佳方式。
工廠模式主要是為建立物件提供過渡介面,以便將建立物件的具體過程遮蔽隔離起來,達到提高靈活性的目的。
工廠模式根據抽象程度的不同分為三種:
簡單工廠模式(也叫靜態工廠模式)
工廠方法模式(也叫多形性工廠)
抽象工廠模式(也叫工具箱)
簡單工廠模式
實質是由一個工廠類根據傳入的引數,動態決定應該建立哪一個產品類(這些產品類繼承自一個父類或介面)的例項。簡單工廠模式的建立目標,所有建立的物件都是充當這個角色的某個具體類的例項。
工廠方法模式
工廠方法是粒度很小的設計模式,因為模式的表現只是一個抽象的方法。 提前定義用於建立物件的介面,讓子類決定例項化具體的某一個類,即在工廠和產品中間增加介面,工廠不再負責產品的建立,由介面針對不同條件返回具體的類例項,由具體類例項去實現。
抽象工廠模式
當有多個抽象角色時使用的一種工廠模式。抽象工廠模式可以向客戶端提供一個介面,使客戶端在不必指定產品的具體的情況下,建立多個產品物件。它有多個抽象產品類,每個抽象產品類可以派生出多個具體產品類,一個抽象工廠類,可以派生出多個具體工廠類,每個具體工廠類可以建立多個具體產品類的例項。
工廠方法模式應該在實際中用的較多,我們以工廠方法模式舉例
(例子來源百度,幫助理解)
抽象的產品類:定義car 交通工具類
public interface Car {
void gotowork();
}
定義實際的產品類,總共定義兩個,bike 和bus 分別表示不同的交通工具類
public class Bike implements Car {
@Override
public void gotowork() {
System.out.println("騎自行車去上班!");
}
}
public class Bus implements Car { @Override public void gotowork() { System.out.println("坐公交車去上班!"); } }
定義抽象的工廠介面
public interface ICarFactory {
Car getCar();
}
具體的工廠子類,分別為每個具體的產品類建立不同的工廠子類
public class BikeFactory implements ICarFactory {
@Override
public Car getCar() {
return new Bike();
}
}
public class BusFactory implements ICarFactory {
@Override
public Car getCar() {
return new Bus();
}
}
簡單的測試類,來驗證不同的工廠能夠產生不同的產品物件
public class TestFactory {
@Test
public void test() {
ICarFactory factory = null;
// bike
factory = new BikeFactory();
Car bike = factory.getCar();
bike.gotowork();
// bus
factory = new BusFactory();
Car bus = factory.getCar();
bus.gotowork();
}
}
工廠模式的優點:
1、一個呼叫者想建立一個物件,只要知道其名稱就可以了,降低了耦合度。
2、擴充套件性高,如果想增加一個產品,只要擴充套件一個工廠類就可以。使得程式碼結構更加清晰。
3、遮蔽產品的具體實現,呼叫者只關心產品的介面。
工廠模式的缺點:
每次增加一個產品時,都需要增加一個具體類和物件實現工廠(這裡可以使用反射機制來避免),使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。所以對於簡單物件來說,使用工廠模式反而增加了複雜度。
工廠模式的適用場景:
1, 一個物件擁有很多子類。
2, 建立某個物件時需要進行許多額外的操作。
3, 系統後期需要經常擴充套件,它把物件例項化的任務交由實現類完成,擴充套件性好。
關於Java中的工廠模式的一些常見問題:
利用父類的向下轉型(使用父類型別的引用指向子類的物件)是可以達到類似於工廠模式的效果的,那為什麼還要用工廠模式呢?
把指向子類物件的父類引用賦給子類引用叫做向下轉型,如:
Class Student extends Person
Person s = new Student();
s = (Student)person ;
使用向下轉型在客戶端例項化子類的時候,嚴重依賴具體的子類的名字。當我們需要更改子類的構造方法的時候,比如增加一個引數,或者更改了子類的類名,所有的new出來的子類都需要跟著更改。
但如果我們使用工廠模式,我們僅僅需要在工廠中修改一下new的程式碼,其餘專案中用到此例項的都會跟著改,而不需要我們手動去操作。(???)
總結:
無論是簡單工廠模式、工廠模式還是抽象工廠模式,它們本質上都是將不變的部分提取出來,將可變的部分留作介面,以達到最大程度上的複用。究竟用哪種設計模式更適合,這要根據具體的業務需求來決定。