通常我們使用Factory方法來處理創建對象的問題,而不必指定將要創建的對象的確切類別。工廠模式下的反射API
可以說我們有一些記錄器的5個不同的實現。下面是僞代碼,將如何與傳統的工廠方法實現:
class LoggerFactoryMethod extends AbstractFactoryMethod {
function makeLogger($param) {
$logger = NULL;
switch ($param) {
case "mysql":
$logger = new MysqlLogger;
break;
case "mongo":
$logger = new MongoLogger;
break;
case "txt":
$logger = new TxtLogger;
break;
case "redis":
$logger = new RedisLogger;
break;
case "memcached":
$logger = new MemcachedLogger;
break;
default:
$logger = new TxtLogger;
break;
}
return $logger;
}
這工作得很好,但有很多的if/else(或開關/碼)的條件下是不是很爽。假設明天我們想添加一個實現。我們需要修改此代碼並添加新的案例條件。有了這個,我們可能會違反SOLID原則中的開放/封閉原則。
相反,使用Reflection API更加優雅,並且不需要對新實現進行重大更改。使用Reflection API的同一個示例應該是:
class LoggerFactoryMethod extends AbstractFactoryMethod {
function makeLogger($param) {
$allowed_implementations = array('mysql','mongo', 'txt', 'redis' , 'memcached');
$class = new ReflectionClass($param);
if (!in_array($param, $allowed_implementations) || !($class->IsInstantiable())){
return null;
}
return $class->newInstance();
}
使用反射API代替傳統工廠模式(使用if/else條件)是否有任何缺點?使用它是好的做法嗎?
我無法PHP說話,但「一般」(其他語言,反射通常比構造更貴,所以你是一個資源開銷造成的),再加上你實際上是限制你的工廠模式,因爲你假定構造函數都是空操作的,如果你有一些操作數,那麼你需要邏輯來啓用它。在一般情況下,工廠擁有if/then/else或某種動態綁定的長列表,但if/then或switch stmt通常更易於處理+更快速且更易於調試(以更多物理代碼爲代價)因此(忽略任何PHP發佈它的權衡'?') – mawalker
我同意@mawalker,並希望傳統的交換機實現。當你想解決簡單的條件時,簡單的條件語句沒有任何問題。由於$ allowed_implementations,當添加新的記錄器實現時,您建議改進的工廠方法也需要修改。 – iluwatar
@iluwatar指出,如果你想超級靈活並支付**反射成本**,只需提取'$ allowed_implementations'集合,以便將其配置爲系統/應用程序屬性,那麼您的工廠將始終可以找到它。 –