2012-03-25 63 views
2

我有以下的策略模式實現:使用工廠創建一個策略

public abstract class RetrievalStrategy { 
    public abstract List<MyObject> retrieve(); 
} 

public class LimitRetrievalStrategy extends RetrievalStrategy { 
    public int limit; 
    public LimitRetrievalStrategy(int limit) { 
     this.limit = limit; 
    } 
    public List<MyObject> retrieve() { 
     // fill up the list and return it, limiting to 'limit' results 
     return new ArrayList<MyObject>(limit); 
    } 
} 

public class SpeedRetrievalStrategy extends RetrievalStrategy { 
    public int speed; 
    public SpeedRetrievalStrategy(int speed) { 
     this.speed = speed; 
    } 
    public List<MyObject> retrieve() { 
     // do something with the speed and return list again 
     return new ArrayList<MyObject>(); 
    } 
} 

我的客戶端應用程序接收無論是速度還是從用戶的限制(可能還有其它參數)。我想創建一個工廠類,它將返回基於具有值的參數和不具有參數的適當策略。我不希望客戶決定應該返回哪個策略。如果工廠createStrategy(params)方法對每個參數都有if語句,並且取決於不同的組合(假設還有其他策略類),那麼返回具體策略類? 這樣做的正確方法是什麼?

+1

這就是我會做的。你有什麼疑問? – 2012-03-25 16:31:04

+0

很難延伸。 – 2012-03-25 16:34:30

+0

TBH,這聽起來像是一個非OO維護的噩夢,讓工廠使用「is-parameter-set」啓發式來猜測使用哪種策略。如果你最終得到兩個使用完全相同參數的策略呢?您將無法使用此工廠設計。 – 2012-03-25 16:38:18

回答

1

不,方法簽名中的返回值應該是通用接口或基類。

工廠必須通過if測試來確定要返回的具體類型,但這是不可避免的,除非您可以製作一個基於封裝參數組合的組合鍵類的具體實例的Map。

4

哦,RetrievalStrategyFactory,從哪裏開始?這聽起來像是一個YAGNI overengineering。一種方法是創建一個枚舉來指定「set」字段,假設每個參數有一個檢索策略,並將其用作工廠。

public enum FieldParameter { 
    LIMIT { 
     RetrievalStrategy getRetrivalStrategy(int value) { 
      return new LimitRetrievalStrategy(value); 
     } 
    }, 
    SPEED { 
     RetrievalStrategy getRetrivalStrategy(int value) { 
      return new SpeedRetrievalStrategy(value); 
     } 
    }; 

    abstract RetrievalStrategy getRetrivalStrategy(int value); 
} 

然後客戶端代碼沒有明確指定檢索策略,但是當客戶端代碼告知您的代碼字段中的用戶提供其隱含給出。

+0

可能有多個值,一個策略可能需要很多參數。 – 2012-03-25 16:33:52

1

如果你需要擴展工廠的能力,你想要一個抽象工廠。這是工廠的一個工廠。一個抽象工廠可以有很多插件工廠,它們可以根據策略來確定使用哪個工廠。

這通常是不必要的複雜,你可以稍後添加,所以它不是你需要做的事情,以防萬一你可能需要它。