6

インターフェイスクラスの使用について明確に理解していません。インターフェイス クラス関連の OOP に関する多くの記事とチュートリアルを読んだので、インターフェイスが何であるかは知っていますが、実際のプロジェクトでの使用については理解しています。

例えば、

IPayment インターフェイス クラスを作成しました。そして、すべての支払いクラスの共通を使用する2つのメソッドを定義しました。

public interface IPayment 
{
  void MakePayment(OrderInfo orderInfo);
  void MakeRefund (OrderInfo orderInfo);
}

CreditCardPayment、PaypalPayment、GooglePayment という 3 つの支払いクラスを作成しました。

各クラスに2つのメソッドを定義しました。

この部分で混乱しています。支払いまたは払い戻しの処理に使用する必要がある注文情報を含む OrderInfo クラスを作成する必要があります。また、各クラスには異なる情報が必要です。

CreditCartPayment クラスにはクレジットカード番号、有効期限が必要です ....しかし、他の支払いクラスは必要ありません。

GooglePayment クラスには Google Order Number が必要ですが、他のクラスには必要ありません。

したがって、最終的に OrderInfo クラスには多くの追加フィールドが必要です。しかも見た目が汚い…。

元)

Public class OrderInfo 
{
  /* For Common */
  string orderNo {get; set;}
  string customerNo { get; set;}
  decimal amount {get; set;}

  /* For Credit Card */
  string CCNum {get; set;}
  string expDate { get; set;}

  /* For Google */
  string googleOrderID {get; set;}
  ...

  /* For Paypal */
  ...
}

私の質問は、

この場合、IPayment を使用するのは正しいですか? または、Interface クラスを使用せずに、各クラスを適切なパラメーターで定義する必要がありますか?

Interface クラスを使用する利点は、後で支払いクラスを簡単に把握できることだと思います。Interface クラスには、各支払いクラスで定義されているメソッドが表示されるためです。他の長所はありますか?

実世界で Interface クラスを理解するためのアドバイスはありますか?

[編集]

アドバイスありがとうございます。

サンプルコードをもう一度書きます。このコードを確認していただけますか?

public interface IPayment 
{
  void MakePayment(OrderInfo orderInfo); // !!
  void MakeRefund (OrderInfo orderInfo); // !!
}

public class OrderInfo 
{
  protected string OrderNo {get; set;}
  protected string CustomerNo { get; set;}
  protected decimal Amount {get; set;}
}

public class CreditCardPaymentInfo : OrderInfo
{
  string CCNum {get; set;}
  string ExpDate { get; set;}
}

public class GooglePaymentInfo : OrderInfo
{
  string GoogleOrderID {get; set;}
}

public class PaypalPaymentInfo : OrderInfo
{
  string PaypalID {get; set;}
}



public void MakePayment()
{
    IPayment paymentModule;
    // Get Order Info 
    if(orderType == "Paypal"){
        paymentModule = new PaypalPayment();

        PaypalPaymentInfo orderInfo = new PaypalPaymentInfo();
        orderInfo.PaypalID = "TEST";
    }else if(orderType == "Google"){
        paymentModule = new GooglePayment();

        GooglePaymentInfo orderInfo = new GooglePaymentInfo();
        orderInfo.GoogleOrderID = "TEST";
    }else{
        paymentModule = new CreditCardPayment();

        CreditCardPaymentInfo orderInfo = new CreditCardPaymentInfo();
        orderInfo.CCNum = "1111111111111111";
        orderInfo.ExpDate = "11/11";
    }

    orderInfo.OrderNo = "123";
    orderInfo.CustomerNo = "ABC";
    orderInfo.Amount = 12.20m;

    paymentModule.MakePayment();
}

エラーが発生します:

エラー 1 'com.WebUI.Models.CreditCardPaymentInfo' はインターフェイス メンバー 'com.WebUI.Models.IPaymentProcess.makeRefund(WebUI.Models.RefundModel)' を実装していません

Interface クラスを修正する必要があると思います。どのように修正すればよいか知っている人はいますか?

4

6 に答える 6

6

1 つのアプローチは、次のようにOrderInfo、基本クラスを作成し、プロバイダー固有の支払いタイプのサブクラスを作成することです。

public class OrderInfo 
{
  /* For Common - Protected members are accessible to subclasses! */
  protected string OrderNo {get; set;}
  protected string CustomerNo { get; set;}
  protected decimal Amount {get; set;}
}

public class CreditCardPaymentInfo : OrderInfo
{
  /* For Credit Card */
  string CCNum {get; set;}
  string ExpDate { get; set;}
}

public class GooglePaymentInfo : OrderInfo
{
  /* For Google */
  string GoogleOrderID {get; set;}
  ...
}

public class PaypalPaymentInfo : OrderInfo
{
  /* For Paypal */
  ...
}

その後、 Payment クラスを次のように実装し、 IPayment インターフェイスの要件を満たすことができます。

public class PaypalPayment : IPayment
{
    public void MakePayment(PaypalPaymentInfo orderInfo)
    {
      ...
    }

    public void MakeRefund (PaypalPaymentInfo orderInfo)
    {
      ...
    }
}

PaypalPaymentInfoが指定されている場所ならどこでも使用できるため、OrderInfoこれは の有効な実装ですIPayment。クレジット カードと Google の支払いの実装についても、同じパターンに従うことができます。

于 2012-11-02T19:32:36.940 に答える
5

これを実装する正しい方法は、支払いの種類ごとにクラスを作成することですが、それらを一般的な として使用しますIPayment。したがって、次のようになります。

public class CreditPayment : IPayment

public class GooglePayment : IPayment

public class PaypalPayment : IPayment

次に、支払いを使用するには:

public class PaymentUser
{
   private IPayment _payment;

   public PaymentUser(//args)
   {
      //Which payment to be used would be based on args. Using a factory here is common
      _payment = new CreditPayment(//args);
   }
}

これIPaymentで、あなたのために作成された ができました。あなたは、それがあなたの契約を満たしていることを知ること以外は、それがどのタイプであるかは気にしません!

だからどこかであなたは言うことができます

public void MakePayment(OrderInfo order)
{
   _payment.MakePayment(order);
}

そして、あなたは自分がどのタイプIPaymentを使用したかさえ知りません。インターフェイスに準拠している限り、どのタイプがメソッドを実行しているかは気にしないため、これにより拡張性が向上しIPaymentます。

于 2012-11-02T19:24:34.180 に答える
1

簡単な例で説明してみましょう。

簡単な方法(たとえば)を考えてみてくださいint rectanglePerimeter(int x, int y)。このメソッドは、単純に2つの数値を取り、それらを乗算して結果を返します。これで、2つの方法で実装できます。

最初:乗算を使用する

    return x*y;

2番目:加算を使用する

    int res = 0;
    for(int i=0; i< length; i++){
      res+= width;
    }
    return res;

このメソッドのコンシューマーコードを実装から独立させたい場合はInterface、メソッドシグネチャを持つをとして定義するだけint rectanglePerimeter(int x, int y)です。これは、さまざまな実装機関によってさまざまな方法で実装される場合がありますが、すべてがメソッド定義に準拠する必要があり、実装に基づいてコンシューマーコードパターンが変更されることはありません。

それでは、インターフェースをDatabase queries execution使用するより実際的な例を見てみましょう。Connectionデータベースプロバイダーは複数あるため、データベースとの接続をサポートするための実装(データベースドライバー)はすべて異なりますが、Connectionインターフェースで定義されているものと同じメソッドサポートを提供します(例:commit()、、、createStatement())。rollback()close()

これにより、使用法は実装に依存しなくなります。ご想像のとおりInterface、消費者とサービスプロバイダーの間でサービス契約の役割を果たしています。コンシューマーとサービスプロバイダーの両方が独自のクラスであるか、2つの異なるグループ/組織からのものである可能性があります。

于 2012-11-02T19:34:05.673 に答える
1

インターフェイスがどのように機能するかについて、いくつか例を示します。とにかく、インターフェースを使用するための多くの側面があり ます

インターフェイスの継承(別名タイプ継承):これはサブタイピングとも呼ばれます。インターフェイスは、通常、各実装クラスに含まれている必要のある共通メソッドのセットを指定することにより、他の点では無関係なクラス間の関係を指定するためのメカニズムを提供します。インターフェイスの継承は、プログラムの設計概念を実装ではなくインターフェイスに促進します。これにより、システム間の結合または実装の依存関係も減少します。Javaでは、任意の数のインターフェースを実装できます。これは、サブクラスの保守を困難にする特定の実装にロックされないため、実装の継承よりも柔軟性があります。したがって、インターフェースを変更して実装クラスを壊さないように注意する必要があります。

例:

という名前のクラスがあるとしましょうPerson

Personには、年齢、名、姓、ID、軍隊ID(たとえば、兵役用)、職場などのフィールドが含まれます。ここで、仕事、軍隊、Facebookなどのいくつかの機関に個人情報を提供したいとします。あなたの仕事は、Facebookであなたの軍隊IDやニックネームについてすべてを聞きたくありません。したがって、いくつかのインターフェイスを作成しますMilitaryItf,。WorkItfWebPersonItf ,WebPersonItf . Inget you define methods/ set Nick name, First Name, gmail and so on. InMilitaryItf you provideget / set`年齢、健康状態、軍隊ID、サービスの開始/終了日....最後に、各機関は「Person」から派生した関心のあるメソッドのみを使用します。

于 2012-11-02T19:39:00.703 に答える
1

インターフェースの目的は、それを実装するオブジェクトへの参照を保持するエンティティが、潜在的に多くの可能な実装のどれであるかを知らなくても、そのオブジェクトを使用できるようにすることです。そのため、インターフェイスは一般に、それを実装するすべてのクラスにとって潜在的に役立つメソッドのみを定義する必要があります。

あなたのシナリオに基づいて、必要なのは支払い処理クラスのインターフェイスではなく、IOrderWithPayment何らかの形式の注文情報をカプセル化することが期待されるオブジェクトのインターフェイスと、それを受け入れることができる支払いプロセッサ オブジェクト (つまり、特定の種類の注文情報)。そのインターフェースには、注文情報を支払い処理業者に提供するメソッドがありますMakePaymentMakeRefundを保持するオブジェクトは、そのIOrderWithPayment中にカプセル化された注文情報または支払いプロセッサのタイプについて心配する必要はありません。これは、実装IOrderWithPaymentするすべてのクラスが、互いに互換性のある注文情報と支払いプロセッサのタイプをカプセル化するためです。

order-info と payment-processor オブジェクトのすべての互換性のある組み合わせを処理できる単一のジェネリック クラスを定義することは可能であることに注意してください。ただし、これらのオブジェクトに、受け入れることができるものに関する適切な宣言が含まれている場合は、かなり高度な概念を使用する必要があります。 . 今のところ、互換性のあるオブジェクトの組み合わせをカプセル化する個別の型を定義する方がおそらく簡単です。

于 2012-11-02T19:57:27.387 に答える
1

インターフェイスは、同じベースから継承しないクラスを使用できるようにするために使用されます。3 つのクラスで行ったことは適切に見えます。ただし、インターフェイスで関数を継承するために使用できる「基本クラス」を作成することもできます。

あなたの問題OrderInfoはインターフェースに起因するのではなく、基本的に別の種類のオブジェクトが必要であるという事実に起因しています。多かれ少なかれ、インターフェイスはCreditCartPaymentクラスに適していません。

1つの方法は、クラスから継承するクラスを作成し、それをOrderInfoクラスCredidCardOrderInfoで使用することCreditCardPaymentです。CreditCardOrderInfoクラスの任意のインスタンスをインスタンスであるかのように使用できOrderInfoます。次に、行を追加します

CreditCardOrderInfo info = orderInfo as CreditCardOrderInfo;
if (info == null) throw new ArgumentException("orderInfo has no credit card order info");

それは物事をまとめます... しかし、それでも汚れています。

于 2012-11-02T19:41:26.163 に答える