2014-08-28 55 views
0

我正在從頭第一本書學習設計模式,我理解他們中的大多數。但是當我嘗試在現實世界中應用時,它變得更加困難。在每個例子中,它創建了很多子類。但是,我們是否真的在實時項目中創建了這麼多課程?在現實世界中的設計模式

E.g.考慮 方法1銀行賬戶的例子:

Account { 

    String name; 
    double balance; 
    operation1() { 
    } 
} 


SavingAccount extends Account { 
    // some extra fields and methods related to saving account 
    operation1() { 
    } 

} 

CurrentAccount extends Account { 
    // Some extra fields and methods related to current account. 
    operation1() { 
    } 

} 

當我使用使用繼承策略的一個休眠,例如地圖這些類與數據庫,每個子類的表,我將結束三個表。帳戶,Saving_account和Current_account。 優點:我可以根據使用多態的對象類型調用operation1()。

缺點:更多的表格和類別。如果項目更加複雜和龐大,最終將會有數千個課程。

方法2:

Account { 
    string name; 
    double balance; 
    string type; 
    operation1() { 
    } 
} 

我只需要1臺這種方法稱爲帳戶。而「類型」字段將標識帳戶的類型。

優點:只有1個表和類。 缺點:我將失去面向對象的世界和每個我必須把條件放在下面的地方。

if (type == saving) { 
    // do this; 
} else if (type == current) { 
    // do that; 
} 

根據理論,方法1是正確和最好的。但是目前在我的項目中,使用了方法2。我的項目不是銀行業務。我把它作爲簡單的例子。

我知道這是非常基本的問題。但由於我目前的項目實施,我無法阻止自己問這個問題。

編輯:的方法1可維護性比方法更更好,因爲你剛纔提到的,你解釋的利弊也有效2.

+2

你在描述什麼設計模式? – 2014-08-28 03:05:42

+0

我只是談論類的一般面向對象設計 – javafan 2014-08-28 03:43:55

回答

3

設計模式,比如繼承很難用它們的重要性來描述,因爲需要一個非常大的項目來實現它的力量。通常的例子落得一樣的東西:

class A { 
} 

class B extends A { 
} 

class C extends B { 
} 

class D extends A { 
} 

然後你得到了很多不那麼現實生活中的問題,如該法foo()真的是指當它實現四個獨立倍。

使用繼承的動機是將相似類型的東西組合在一起。一個基本的例子是,如果你想在一個列表中有一堆不同的對象。如果它們都是不同的類型,這是不可能的,但如果它們處於繼承層次結構中,則可以將它們組合在一起。

對於你的榜樣,你可以把每一個Account對象到一個列表,無論哪個子類的對象是真的。

List<Account> list = new ArrayList<Account>(); 
list.add(new Account()); 
list.add(new SavingsAccount()); 
list.add(new CurrentAccount()); 

說要處理該列表中的每一件事情。如果你有一個常用的方法,您可以使用多態,使每個Account做自己的具體行動:

for(Account a : list) { 
    a.operation1(); 
} 

不必爲每種類型的對象的單獨列表簡單多了,不是嗎?然後,如果您想創建更多類型的帳戶,如果擴展基類Account類,則不必爲代碼添加新列表和新循環。一切都可以保持原樣。

使用繼承還有助於使用其他人編寫的代碼。如果你想添加一些東西給其他人編寫的類,你可以將它包含在一個包中,然後用你自己的一個類來擴展它。這樣你就不需要做很多複製和粘貼操作,並且瀏覽其他類的源代碼。即使您只有.class文件,也可以擴展另一個類,而不是.java文件中的源代碼。

所以繼承的力量取決於你如何使用它。在一個小例子中,它並不合理。但是項目越大,意義越大。

+0

是的,我的項目非常複雜和大。那麼你是否建議在這種情況下使用方法1? – javafan 2014-08-28 03:45:47

+0

是的,當然它將取決於你的項目的具體結構。一般來說,項目越大越複雜,使用繼承就越有意義。就設計的任何方面而言,我建議使用多種設計模式概述您的項目,然後選擇最有意義的項目。 – jackarms 2014-08-28 03:56:05

1

這兩種方法都是有效的。

但是,舉例來說,如果您將此會計軟件包(編譯的jar)作爲庫文件供其他人使用,則方法1是理想的,因爲;

  1. 您不需要修改Account的任何源代碼,只需擴展它,然後實現您自己的版本即可。例如: - FixedDepositAccount
  2. 不會破壞您的Account代碼。
  3. 沒有再次Account.operation1()

需要測試的,但如果你願意分享的源代碼,並願意做上述步驟,然後最好是使用方法2

+1

代碼的可維護性與方法2的問題是正確的嗎? – javafan 2014-08-28 03:46:41

0

在Java中,我們可以有String type;(不string type;),但更重要的將是一個Enum類型(這樣我們可以有增加貨幣市場賬戶或鉑首選儲蓄賬戶,可能不重新實現主叫代碼) 。喜歡的東西,

enum AccountType { 
    CHECKING(0.005), SAVINGS(0.01), MMA(0.02); 
    final double rate; 

    private AccountType(double rate) { 
     this.rate = rate; 
    } 
    public double getRate() { 
     return this.rate; 
    } 
} 

而且具有AccountType你可以安全地使用==平等,同時用Stringif (type == saving) {是自找麻煩。那就是

if (type == AccountType.CHECKING) { 
} else if (type == AccountType.SAVINGS) { 

將按照您的預期工作。最後,最好避免使用if鏈,而是在你可以的時候將你打算使用帳戶類型進行的任何操作封裝到枚舉中。例如,

Account acct = getAccount(accountNumber); 
if (acct != null && acct.isValid()) { 
    acct.balance += acct.balance * type.getRate(); 
} 
+0

我提到的代碼只是僞代碼。這不是確切的代碼。那麼你是否建議方法2? – javafan 2014-08-28 04:19:06

+0

@javafan請用真實的代碼更新您的問題,我只能根據您發佈的內容回答。 – 2014-08-28 04:33:22

+0

我只是想了解如何使用此銀行帳戶示例在複雜場景中設計類和相應表。我沒有任何特定的代碼。 – javafan 2014-08-28 04:45:37