(304)Replace_Constructor_With_Factory_Method

已工廠代替建構

希望在建立物件時不僅僅是對他做簡單的建構動作,

建立的動作散過各地,需要調整,必須每個地方都修正,造成困擾

Employee (int type) {
    _type = type;
}

轉換成

static Employee create (int type) {
    return new Employee(type);
}

動機

可能需要根據傳入的參數來建立相對應的物件

作法

  1. 建立一個factory method,讓他呼叫現有的建構式
  2. 將建構式的呼叫,改成factory method

範例1:根據整數 創建物件

class Employee {
    private int _type;
    static const int ENGINEER = 0;
    static const int SALESMAN = 1;
    static const int MANAGER = 2;

    Employee (int type) {
        _type = type;
    }
}

class Employee {
    private int _type;
    static const int ENGINEER = 0;
    static const int SALESMAN = 1;
    static const int MANAGER = 2;

    Employee (int type) {
        _type = type;
    }

    // 建立一個factory method
    static Employee create (int type){
        return new Employee(type);
    }

    // client code
    Employee eng = Employee.create(Employee.ENGINEER);
}

範例2:根據字串 創建subclass 物件

如果使用 (223)Replace_Type_Code_with_Subclasses把type code 轉換成 Employee的subclass

就可以運用 factory method,將這些subclass對使用者隱藏起來

static Employee create(int type){
    switch (type){
        case ENGINEER:
            return new Engineer();
            break;
        case SALESMAN:
            return new Salesman();
            break;
        case MANAGER:
            return new Manager();
            break;
    }
}

這邊有一個缺點,每新增一個subclass就要記得加入Switch

解法:ClaSS.forName() 這邊範例使用的是java 需要自己轉換C#

第一:修改參數型別,可參考 (273)Raneme_Method

首先建立一個Function,讓他接收參數

static Employee create (string name){
    try{
        return (Employee) Class.forName(name).newInstance();
    }
    catch(Exception e){
        throw new .....
    }
}

// clint code
Employee.create(ENGINEER);

改成

employee.create("Engineer");

這樣就可以自動建立,但失去了編譯時期的檢查

範例3:已明確函式(Explicit Methods)創建 subclass


class Person {

    static Person CreateMale(){
        return new Male();
    }

    static Person CreateFemale(){
        return new Female();
    }
}

// client
Person kent = new Male();
改成
Person kent = Person.crateMale();

後繼

範例一跟範例二是我常常使用的方法,但方法二的forname這段可以再補上加強寫法

我這邊最常使用的場景多半是用在工廠模式,需要根據不同狀況去建立物件

類似MOMO、YAHOO、PCHOME對帳,對帳的動作全部都是一樣的,只是裡面實作不同

所以通常會使用方法二來 return 我要的物件

  1. 建立虛擬類別
  2. SubClass 繼承虛擬類別實作其方法
  3. 使用factory method 或 工廠模式 來創建我想要的物件