2

食料品店で顧客の領収書を印刷する簡単なプログラムを作成するという課題が与えられました。基本的な消費税は、免除される本、食品、医療製品を除くすべての商品に10%の税率で適用されることを知ってください。輸入税は、すべての輸入品に5%の税率で適用される追加の消費税であり、免税はありません。

入力例:1冊が$ 10、1冊の輸入チョコレートバーが$5など。

プログラムをできるだけオブジェクト指向にしたいと思っています。したがって、私の階層は次のようになります。

最上位の階層は抽象クラスItem(name、price)で、次にクラスSaleTaxItem(10%の税金を支払う必要があるアイテム)があり、NonSaleTaxアイテムクラスはItemから拡張されます。問題は、上記の各クラス内にisImportedというブール変数を作成して、5%多く請求する時期を知る必要があるかどうかです。または、インポートされたアイテムの新しいクラスを作成する必要がありますか?

この課題ではデザインが非常に重要なので、完璧にしたいと思います。ありがとう!

4

1 に答える 1

2

継承を使用する場合と使用しない場合については、多くの議論があります。この場合、私はあなたのアイテムをモデル化するために継承を使用しません。

なんで?実生活では、これらの税金と関税の規則は、時間、スペース(たとえば、どの州にいるか)と、経営している会社の種類の両方で頻繁に変更されるためです。地方自治体や連邦政府が規制を変更するたびにクラス階層を変更する必要がある場合、あなたは運命にあります-更新により、すでにインスタンスを持っているクラス-アイテムが変更されます。

別の考慮事項:クラスを使用して、販売に税金や義務があるものとして(効果的に)「タグ付け」する場合、タグ付けインターフェースを持たないアイテムと、複数のアイテム、つまり多重継承を使用するアイテムになります。4つのクラスが必要です。いくつかのルールを追加すると、クラスが急増します(考慮すべき税金/義務の階乗数)。

別の実装は、アイテムが持つ税金と義務の集合であるプロパティを持つことです。したがって、2つのクラスがあります。

  • アイテム

    • リスト:税金
    • 文字列:名前
    • ダブル:パーセント

Taxには、SalesTaxとImportDutyなどのグローバルインスタンスがいくつかあります。次に、アイテムのリストに0、1、または2つのTaxインスタンスがあります(リストには、税金が適用される順序も含まれています)。

この最後のアプローチは、新しい税金の追加など、税金の変更に対してもはるかに将来性があります。

一晩編集私は改善された提案があります:

ここに画像の説明を入力してください

この図には2つの「翼」があります。

  1. AbstractItem階層、アイテムとその税金の処理
  2. TaxOrDuty階層とTaxAssessorのアルゴリズム。

AbstractItemは、アイテムのデコレータパターンを使用して、アイテムを税金のレイヤー(TaxedItemによってモデル化された各レイヤー)でラップします。最外層は、該当するすべての税金で包まれたアイテムであり、デコレータパターンを使用して、価格が高騰していることを除いて、アイテムと同じように見え、動作します。AbstractItemには、いくつかの便利なメソッドがあります。

  • getPrice():アイテムの全額を返します
  • getAllTaxes():空のリストを渡すと、メソッドは、TaxOrDutyインスタンスを収集するデコレータを繰り返し処理します。これは、装飾されたアイテムの税金を明細化できるようにするために重要です
  • getUntaxedItem():アイテムが見つかるまで装飾を繰り返し、アイテムを返します。これにより、装飾されたアイテムから生のアイテムを簡単に取得できます。

税金の面では、一般的な税金の抽象的な振る舞いをモデル化するクラスTaxOrDutyがあります。この単純な実装では、すべての税金の税率は定額ですが、その動作をFlatRateTaxクラスに簡単にプッシュできます。そのメソッドは次のとおりです。

  • getRate():税金または関税を返す抽象メソッド。これはサブクラスに実装されています
  • ComputeTax()メソッドはアイテムを受け取り、getRate()に基づいてアイテムの税金を計算します
  • isApplicable()は、税金がアイテムに適用される場合にtrueを返す抽象メソッドです。これは、SalesTax(常にtrueを返す)とImportDuty(Item.isImportedを返す)に実装されています

TaxAssessorは、該当する税金の割り当てを調整する責任があるクラスです。これには、すべてのTaxOrDutyインスタンスのリストが含まれています(この場合、SalesTaxの1つのインスタンスとImportDutyの1つのインスタンスのみ)。そのメソッドapplyTaxes(Item)は、isApplicable()を呼び出してこのコレクションを反復処理します。trueを返すTaxOrDutyの場合、TaxAssessorはItemを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>());

このモデルの主な利点は次のとおりです。

  • 新しい税金は差し込むことができます
  • 税の査定と計算のアルゴリズムは、アイテムではなく税の一部であるため、非常に複雑な税を独自のクラスで独立して正しくモデル化できます。
  • 責任は(私には)明白であり、明確に区別されています
于 2013-02-20T06:55:45.327 に答える