デザインパターン|アダプターパターン

1 |アダプタモードの概要

一般的な生活現象を考えてみましょう。我が国の生活用電気電圧は220Vですが、携帯電話、ノート、テレビなどの実際の動作電圧はそれほど高くありません。これらの機器が220Vの生活用電気を使用するには、電源アダプタ(AC Adpater)は、充電器や変圧器でもあります。この電源アダプタを使用すると、直接動作できない家庭用電化製品などの機器との互換性があり、その中の電源アダプタがアダプタとして機能します。

同様にソフトウェア開発においても、このような非互換性が発生することがあります。電源アダプタのようなアダプタと呼ばれる役割を導入して、これらの非互換性のある構造を調整することもできます。この設計スキームがアダプタモードです。 

電源アダプタと同様に、アダプタと呼ばれるパッケージングクラスがアダプタモードで導入され、それがラップするオブジェクトは、適応されるクラスであるAdapteeと呼ばれます。アダプタの実現は、クライアントクラスの要求をアダプタの対応するインターフェイスへの呼び出しに変換することです。つまり、クライアントクラスがアダプタのメソッドを呼び出すと、アダプタクラスのメソッドがアダプタクラス内で呼び出され、このプロセスはクライアントクラスに対して透過的であり、クライアントクラスはアダプタに直接アクセスしません。クラス。したがって、アダプタを使用すると、互換性のないインターフェイスが原因で相互作用できないクラスを連携させることができます。

1.1アダプタモードの定義

  • アダプターパターン:クラスのインターフェースを顧客が望む別のインターフェースに変換します。アダプタモードでは、互換性のないインターフェイスを持つクラスが連携できます。
  • アダプタパターン:クラスのインターフェイスを、クライアントが期待する別のインターフェイスに変換します。アダプターを使用すると、互換性のないインターフェースのために他の方法では不可能だったキャスを連携させることができます。

アダプタパターンは、元のアダプタインターフェイスと抽象ターゲットインターフェイスクラスを変更せずに、あるクラスのインターフェイスを別のクラスのインターフェイスと一致させることができます。

アダプタパターンのエイリアスはラッパーパターンであり、クラス構造パターンまたはオブジェクト構造パターンのいずれかとして使用できますアダプターパターン定義で言及されているインターフェースは、メソッドまたはメソッドのコレクションを表すことができる幅広いインターフェースを指します。

2 |アダプタパターンの構造と実装

アダプタパターンには、クラスアダプタとオブジェクトアダプタが含まれます。オブジェクトアダプタパターンでは、アダプタとアダプタの間に関連付け関係があります。クラスアダプタパターンでは、アダプタとアダプタには継承(または実現)関係があります。以下は、2つのアダプターの構造分析です。

2.1アダプタモードの構造

アダプターモードには、次の3つの役割が含まれます

  • (1)ターゲット(ターゲット抽象クラス):ターゲット抽象クラスは、顧客が必要とするインターフェースを定義します。これは、抽象クラスまたはインターフェース、あるいは具象クラスです。クラスアダプタでは、C#言語機能により、単一の継承と複数のインターフェイス拡張があります。
  • (2)アダプタ(アダプタクラス):別のインターフェイスをコンバータとして呼び出して、AdapteeとTargetを適応させることができます。アダプタはアダプタパターンのコアです。クラスアダプタでは、Targetインターフェイスを実装してAdapteeクラスを継承することで2つを接続します。オブジェクトアダプタでは、Targetを継承してAdapteeオブジェクトを関連付けることで2つを接続します。
  • (3)Adaptee(アダプタクラス):アダプタは、適応する必要のある役割です。これは、適応する必要のある既存のインターフェイスを定義します。アダプタクラスは通常、特定のクラスであり、文にはクライアントが含まれます。場合によっては、アダプタクラスのソースコードが使用されていないこともあります。

2.2アダプタモードの実装

アダプタモードには、クラスアダプタモードとオブジェクトアダプタモードの2つの形式が含まれているため、以下では、これら2つのアダプタモードの実装メカニズムについて説明します。

2.2.1クラスアダプタ

クラスアダプタでは、アダプタクラスAdapteeにはBeavast()メソッドがなく、クライアントはこのメソッドを期待しますが、SpecificRequest()メソッドはアダプタクラスに実装されます。このメソッドによって提供される実装は、まさにクライアントが必要とするものです。 。顧客がアダプタクラスを使用できるようにするために、中間クラス、つまりAdaptetクラスが提供されます。アダプタクラスは、オブジェクトオブジェクトクラスインターフェイスTargetを実装し、アダプタクラスを継承します。アダプタクラスのReqpest()で、メソッドは次のように呼び出します。適応の目的を達成するための、継承されたアダプタクラスのSpecificRequest()メソッド。アダプタクラスアダプタクラス継承されるため、このアダプタモードはクラスアダプタモードと呼ばれます。一般的なクラスアダプタコードは次のとおりです。

interface ITarget
{
    string Request();
}

class Adaptee
{
    public string SpecificRequest() => "Adaptee.SpecificRequest";
}

class ClassAdapter : Adaptee, ITarget
{
    public string Request() => $"ClassAdapter.Request 调用 {base.SpecificRequest()}";
}

2.2.2オブジェクトアダプタ

オブジェクトアダプタでは、クライアントはRequest()メソッドを呼び出す必要がありますが、Adapteeクラスにはこのメソッドはありませんが、それが提供するSpecificRequest()メソッドはクライアントが必要とするものです。クライアントがアダプタクラスを使用できるようにするには、ラッパークラスAdapter、アダプタクラスを提供する必要があります。このラッパークラスは、アダプターのインスタンスをラップしてクライアントをアダプターに接続し、アダプターのRequest()メソッドでアダプターのSpecificRequest()メソッドを呼び出します。のでアダプタクラスアダプタクラスをしている団体の関係(とも呼ばれる委任関係)、このアダプタパターンは、オブジェクトアダプタパターンと呼ばれています。一般的なオブジェクトアダプタコードは次のとおりです。

class ObjectAdapter : ITarget
{
    private readonly Adaptee _Adaptee; //维持一个适配者对象的引用

    public ObjectAdapter(Adaptee adaptee)
    {
        _Adaptee = adaptee;
    }

    public string Request() => $"ObjectAdapter.Request 调用 {_Adaptee.SpecificRequest()}";
}

アダプタパターンは、あるクラスのインターフェイスを別のクラスのインターフェイスと一致させることができます。これを使用する前提は、元のアダプタインターフェイスと抽象ターゲットクラスインターフェイスを変更できない、または変更したくないということです。例:一部のサードパーティクラスのライブラリまたはコントロールを購入しましたが、ソースコードはありません。現時点では、アダプタモードを使用してオブジェクトアクセスインターフェイスを統合できます。
アダプターパターンは、関数の実現よりも、コードの編成に重点を置いています。実際の開発では、オブジェクトアダプタの使用頻度が高くなっています。

クライアントコール

3 |アダプタパターンの適用例

コードデザイン

  1. ScoreOperation:ターゲットインターフェイスとして機能する抽象スコア操作クラス。
  2. QuickSortClass:アダプターとして機能するクイックソートクラス。
  3. BinarySearchClass:適応クラスとして機能するバイナリ検索クラス。
  4. 構成ファイルApp.configは、アダプタークラスのクラス名(フルネーム)を構成ファイルに格納します。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="adapter" value="AdapterPattern.Sample.OperationAdapter"/>
  </appSettings>
</configuration>

上記のコードの詳細については、以下を確認してください=》https://gitee.com/dolayout/DesignPatternOfCSharp/tree/master/DesignPatternOfCSharp/AdapterPattern

クライアントコール

4 |デフォルトのアダプターモード

デフォルトのアダプタモードはアダプタモードの変形であり、そのアプリケーションもより普及しています。このモードは、シングルインターフェイスアダプタモードとも呼ばれます

4.1デフォルトのアダプタモードの定義

  • デフォルトのアダプタパターン:インターフェイスによって提供されるすべてのメソッドを実装する必要がない場合は、最初にインターフェイスを実装する抽象クラスを設計し、インターフェイスの各メソッドにデフォルトの実装(空のメソッド)を提供し、次にサブクラスを提供できます。この抽象クラスのは、要件を達成するために親クラスの一部のメソッドを選択的にオーバーライドできます。これは、単一インターフェイスアダプタモードとも呼ばれるインターフェイスですべてのメソッドを使用したくない状況に適しています。

4.2デフォルトのアダプタモードには、次の3つの役割が含まれています。

  • (1)IServiceInterface(アダプタインターフェイス):これはインターフェイスであり、通常、多数のメソッドがインターフェイスで宣言されます。
  • (2)AbstractServiceClass(デフォルトのアダプタークラス):これは、デフォルトのアダプターパターンのコアクラスであり、ServiceInterfaceインターフェイスで宣言されたメソッドを空のメソッドの形式で実装します。インスタンス化しても意味がないため、通常は抽象クラスとして定義されます。
  • (3)ConcreteServiceClass(特定のサービスクラス):デフォルトのアダプタクラスのサブクラスです。アダプタを導入する前に、アダプタインターフェイスを実装する必要があるため、アダプタインターフェイスで宣言されているすべてのメソッドを実装する必要があります。一部のメソッド使用する必要のないものは、空の実装を提供する必要があります。デフォルトのアダプタを使用した後、アダプタクラスを直接継承し、必要に応じてアダプタクラスで定義されたメソッドを選択的にオーバーライドできます。

その中で、デフォルトのアダプタークラスの典型的なコードスニペットは次のとおりです。

interface IServiceInterface 
{
    void ServiceMethod1();
    void ServiceMethod2();
    void ServiceMethod3();
}

abstract class AbstractServiceClass : IServiceInterface
{
    public void ServiceMethod1() { } // 空方法
    public void ServiceMethod2() { }
    public void ServiceMethod3() { }
}

5 |双方向アダプターモード

オブジェクトアダプタの使用中に、アダプタにターゲットクラスとアダプタクラスの両方への参照が含まれている場合、アダプタはそれを使用してターゲットクラスのメソッドを呼び出すことができ、ターゲットクラスはそれを介してアダプタクラスを呼び出すこともできます。メソッドの場合、アダプタは双方向アダプタです。

双方向アダプターの実装はより複雑であり、その典型的なコードは次のとおりです。

class TwoWayApapter : Adaptee, ITarget
{
    // 同时维持抽象目标类和适配者的引用
    private readonly Adaptee _Adaptee;
    private readonly ITarget _Target;

    public TwoWayApapter(Adaptee adaptee) 
    {
        _Adaptee = adaptee;
    }

    public TwoWayApapter(ITarget target)
    {
        _Target = target;
    }

    public new string SpecificRequest() => _Target.Request();

    public string Request() => _Adaptee.SpecificRequest();

}

6 |アダプタモードと適用可能な環境の長所と短所

アダプターパターンは、既存のインターフェースを顧客クラスが期待するインターフェースに変換し、既存のクラスの再利用を実現します。これは、非常に頻繁に使用されるデザインパターンであり、ソフトウェア開発で広く使用されています。

6.1アダプタモードの利点(オブジェクトアダプタモードとクラスアダプタモードの両方)

  • (1)ターゲットクラスとアダプタクラスを分離し、元の構造を変更せずにアダプタクラスを導入して既存のアダプタクラスを再利用します。
  • (2)クラスの透明性と再利用性を高め、特定のビジネス実現プロセスをアダプタークラスにカプセル化します。これは、クライアントクラスに対して透過的であり、アダプターの再利用性を向上させます。1つは、アダプタークラスを複数で再利用できることです。さまざまなシステム。
  • (3)柔軟性とスケーラビリティが非常に優れています。構成ファイルを使用することで、アダプタを簡単に交換でき、元のコードを変更せずに新しいアダプタクラスを追加できます。これは、開始と終了の原則に完全に準拠しています。

具体的には、クラスアダプタパターンには次の利点もあります。

  • アダプタクラスはアダプタクラスのサブクラスであるため、一部のアダプタメソッドをアダプタクラスで置き換えて、アダプタをより柔軟にすることができます。

オブジェクトアダプタモードには、次の利点もあります。

  • (1)オブジェクトアダプタは、複数の異なるアダプタを同じターゲットに適合させることができます。
  • (2)オブジェクトアダプタモードは、アダプタのサブクラスに適応できます。アダプタとアダプタは関連付けられているため、リヒター置換の原則に従って、アダプタのサブクラスもアダプタを介して適応できます。

6.2
アダプタモードのデメリットクラスアダプタモードの主なデメリットは次のとおりです。

  • (1)C#やJavaなど、複数のクラスの継承をサポートしていない言語の場合、一度に最大1つのアダプタークラスを適応させることができ、同時に複数のアダプターを適応させることができます。
  • (2)アダプタクラスを最終クラスにすることはできません。たとえば、C#で封印されたクラスにすることはできません。
  • (3)C#やJavaなどの言語では、クラスアダプターパターンのターゲット抽象クラスはインターフェイスのみであり、クラスではなく、その使用には特定の制限があります。

オブジェクトアダプタパターンの主な欠点は次のとおりです。

  • クラスアダプタパターンと比較して、アダプタ内のアダプタクラスを置き換えるいくつかの方法はより面倒です。アダプタクラスの1つ以上のメソッドを置き換える必要がある場合は、最初にアダプタクラスのサブクラスを作成し、アダプタクラスのメソッドを削除してから、アダプタクラスのサブクラスを実際のアダプタの適応プロセスとして扱うことができます。より複雑です。

6.3アダプタモードの適用環境

  • (1)システムはいくつかの既存のクラスを使用する必要があり、これらのクラスのインターフェース(メソッド名など)はシステムのニーズを満たしていないため、これらのクラスのソースコードすらありません。
  • (2)将来導入される可能性のあるクラスを含め、相互にあまり関連性のないクラスを処理するための再利用可能なクラスを作成します。

 

おすすめ

転載: blog.csdn.net/ChaITSimpleLove/article/details/115056329