關於何時使用繼承以及何時不使用,存在着巨大的討論。在這種情況下,我會而不是使用繼承來建模您的項目。
爲什麼?因爲在現實生活中,這些稅收和責任規則在時間,空間(例如你所在的國家)以及你正在運行的公司類型中經常發生變化。如果每當地方政府和聯邦政府更改其規定時都必須更改班級層級,那麼您註定會失敗 - 更新會更改您已擁有實例的班級 - 您的項目。另一個考慮:如果您使用類(有效地)將銷售標記爲具有稅收和/或責任,那麼您將最終得到一些沒有標記接口的項目,並且一些項目具有多個 - 即使用多重繼承。你需要四個班級。添加一些額外的規則,並且你有一個班級爆炸(考慮稅種/職責數量的因子)。
另一種實現方式是擁有一個屬性,該屬性是項目所具有的稅收和關稅的集合。所以,你有兩個班,:
稅收有許多全局實例 - SalesTax和ImportDuty。然後,一個項目在列表中具有零個,一個或兩個Tax實例(並且該列表還暗示訂單納稅被應用)。
這最後一種方法也是更好的適應未來的稅制改革,包括增加新稅種
編輯一夜之間我有一個改進的建議:
有兩種'wings'to the diagram:
- AbstractItem層次結構,處理Item和i稅收
- TaxOrDuty層次結構和TaxAssessor中的算法。
AbstractItem在Item上使用decorator pattern,將Item包裝在稅層中 - 每個層由TaxedItem建模。最外層是包裹在所有適用稅款中的物品,並且使用裝飾者模式,除了虛高價格外,其外觀和行爲都與物品相同。該AbstractItem有幾個有用的方法:
- 用getPrice():返回全價的項目
- getAllTaxes()的:通過在一個空的列表,以及遞歸方法在裝飾收集TaxOrDuty實例。這對於能夠對裝飾物品的稅收進行分項很重要
- getUntaxedItem():通過裝飾物遞歸直到它找到它返回的物品。這可以輕鬆從裝飾物品中檢索原始物品。
在稅收方面,有一類TaxOrDuty模擬稅收的抽象行爲。在這個天真的實現中,每個稅都有一個統一的稅率,但是您可以輕鬆地將該行爲推到FlatRateTax類中。其方法是:
- 的getRate():返回稅收或關稅率摘要方法。這是在子類上實現的
- computeTax()方法獲取一個項目並根據getRate()計算稅金
- isApplicable()是一個抽象方法,如果稅項適用於Item,則返回true。這在SalesTax上執行(總是返回true)和ImportDuty(返回Item.isImported)
TaxAssessor是負責協調適用稅收分配的類。它包含所有TaxOrDuty實例的列表(在本例中只是SalesTax的一個實例和ImportDuty之一)。它的方法applyTaxes(Item)遍歷這個集合調用isApplicable()。對於返回true任何TaxOrDuty,該TaxAssessor包裹項目在TaxedItem(當然它引用TaxOrDuty)的新實例:
AbstractItem applyTaxes(Item item) {
taxed = item;
for (TaxOrDuty td : taxes) {
if (td.isApplicable(item)) {
taxed = new TaxedItem(td, taxed);
return taxed;
所以你的整體答案是這樣的:
Item item = new Item("Book", 10.0, false); // New $10 book, not imported
AbstractItem withTaxes = taxAssessor.applyTaxes(item);
double taxedPrice = withTaxes.getPrice();
List<TaxOrDuty> applicableTaxes = withTaxes.getAllTaxes(new List<TaxOrDuty>());
這種模式的主要優點是:
- 新稅種是可插拔
- 納稅評估和計算算法是稅收的一部分,而不是在項目,所以非常複雜的稅收可以在自己的階級獨立且準確地模擬
- 責任是明顯的(對我來說),並明確劃定
爲什麼不只是寫一個方法'getTax ()'哪些返回10%的SaleTaxItem和10%+ 5%的項目是否可以進口(可能重寫?)?我不認爲布爾是一個很好的可擴展選擇:想象一下,我們引入了新的稅收:我們是否需要引入新的布爾值?我們是否需要在int中進行編碼? – 2013-02-20 06:45:44
雅我有getTax()其中我目前使用布爾值來決定是否收取5%的進口稅。我在Item類中實現了is_import布爾值。如果我不使用布爾值,那麼我應該使用什麼? – 2013-02-20 07:03:44