2009-10-06 54 views
1

我有以下的設計決策 - 第二次運行它,所以我希望我不是唯一的一個...Python中的對象設計模式問題

我有各種各樣的命令類代表一些行動。每個Command類(有很多,比如說SleepCommand,RunCommand,MeasureCommand)具有不同的參數和默認值等等,但最後每個都有一個generate()方法返回一些打包表示。

現在,我還有一個CommandSequence類,可以彙總列表中的許多命令。它有自己的generate()方法來完成一些自定義工作,爲列表中的所有命令運行generate(),添加自己的東西等等。

我對如何創建這些命令對象有疑問。有幾種選擇:

(1)讓用戶創建各種Command對象的實例,並在CommandSequence上調用add_command()方法 (2)在CommandSequence中爲每個可能的命令創建一個「工廠方法」 。工廠方法接受Command的參數並將它們傳遞給Command構造函數。 (3)由於方法(2)重複代碼(對象的構造函數初始化列表),我可以讓所有工廠方法接受*args, **kwargs並將它們傳遞給對象。

現在,方法(1)不重複代碼,但暴露了過多的Command類給用戶。相對於(2)用戶代碼是更詳細:

# seq is a CommandSequence object 
seq.add_command(SleepCommand(time='10 ms', wakeup_alarm=False)) 

,而不是:

seq.sleep(time='10 ms', wakeup_alarm=False) 

因爲我建立一個怎樣的一個DSL,用戶代碼急促和清晰度是非常重要的對我來說。我可以使用方法(3)來保存代碼重複,然後在哪裏放置Command類的文檔 - 在工廠方法或類的構造函數中。

我在這裏錯過了一些明顯的模式?你會如何處理這個問題?

+1

由於你正在談論一個'CommandSequence'對象的方法,我會認爲'add'就像' add_command',這使得你的第一個選項不那麼冗長。就個人而言,如果有意義的話,我會讓CommandSequence成爲列表的一個子類,或者將相同的接口作爲列表公開,以實現最大的實用性和最小的學習。 – spookylukey 2009-10-06 09:55:42

回答

3

我會用1

堅持當您有執行SleepCommand所需的代碼的一部分,這對我來說很有意義的SleepCommand建設接口暴露在那部分代碼。他們還能如何構建一個?

你可以使用工廠,但我不認爲它在這裏獲得了很多(除了你指出的代碼重複)。這也意味着每次需要添加新命令時,都需要更改CommandSequence類以公開一個接口來執行新命令。這違反了開閉原則(http://en.wikipedia.org/wiki/Open/closed_principle)。

編輯:另一個重要的問題是數字1是一個更簡單的設計。要添加新的命令,只需創建一個新的命令類 - 這是很好的OO設計。另外,用你在問題中寫的兩行代碼,我不認爲第二行比第一行復雜得多。

1

還有一個選擇是,

步驟1.創建CommandSequence的構造,通過可變參數列表

步驟2發生在多個命令對象。創建靜態常量(我不是Python編程,所以請原諒,如果這是不可能的)CommandSequence類型的對象「內部」CommandSequence用常用命令序列的命令初始化。

這將幫助客戶在編寫代碼就像

CommandSequence.XYZCommandSeq.generate 

有助於避免在許多地方重複。

0

我會避免(3)。你鬆散的文檔...所以你將不得不重複的東西...

對於(1),你提到調用開發人員需要知道的過多的對象。但是這些對象正是調用開發者需要知道的東西,所以它看起來像是一個必要的複雜性。

對於(2),如你所說,它是重複的。
另外,對於每一個新的命令,你將不得不保持你的工廠方法......