工廠方法模式
定義: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
方法通常是靜態的,所以也稱之為靜態工廠。
缺點:擴充套件性差,當我們需要增加一個產品類時還需要修改工廠類; 不同的產品需要不同額外引數的時候 不支援。
多方法靜態工廠
簡單工廠模式的一個問題是 當產品需要不同額外引數的時候 不支援。
而且如果使用時傳遞的 type
、Class
出錯,將不能得到正確的物件,容錯性不高。
而多方法的工廠模式為不同產品,提供不同的生產方法。
基本組成 |
---|
產品抽象類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
方法,多方法靜態工廠模式需要增加一個靜態方法。
缺點:引入抽象工廠層後,每次新增一個具體產品類,也要同時新增一個具體工廠類。