サーチ…


アダプタパターン(PHP)

異なるタイプの組織で特定のルーチンが実行される科学実験を使用した実際の世界の例。クラスには、ティッシュまたはルーチンを別々に取得するために、デフォルトで2つの関数が含まれています。それ以降のバージョンでは、新しいクラスを使用してそれを適用し、両方を取得する関数を追加しました。つまり、元のコードを編集していないため、既存のクラスを破る危険性はなく(再テストも必要ありません)。

class Experiment {
    private $routine;
    private $tissue;
    function __construct($routine_in, $tissue_in) {
        $this->routine = $routine_in;
        $this->tissue  = $tissue_in;
    }
    function getRoutine() {
        return $this->routine;
    }
    function getTissue() {
        return $this->tissue;
    }
}

class ExperimentAdapter {
    private $experiment;
    function __construct(Experiment $experiment_in) {
        $this->experiment = $experiment_in;
    }
    function getRoutineAndTissue() {
        return $this->experiment->getTissue().' ('. $this->experiment->getRoutine().')';
    }
}

アダプタ(Java)

あなたの現在のコードベースにはMyLoggerインターフェースが存在すると仮定します。

interface MyLogger {
    void logMessage(String message);
    void logException(Throwable exception);
}

MyFileLoggerMyConsoleLoggerなど、いくつかの具体的な実装を作成したとします。

アプリケーションのBluetooth接続を制御するフレームワークを使用することに決めました。このフレームワークには、次のコンストラクタを持つBluetoothManagerが含まれています。

class BluetoothManager {
    private FrameworkLogger logger;

    public BluetoothManager(FrameworkLogger logger) {
        this.logger = logger;
    }
}

BluetoothManagerはロガーも受け付けます。これは素晴らしいことです!しかし、フレームワークによってインタフェースが定義されたロガーが必要であり、関数の名前を変更する代わりにメソッドのオーバーロードが使用されています。

interface FrameworkLogger {
    void log(String message);
    void log(Throwable exception);
}

再利用したいMyLogger実装がすでにありますが、 FrameworkLoggerインターフェースには適合しません。これは、アダプターのデザインパターンが入る場所です。

class FrameworkLoggerAdapter implements FrameworkLogger {
    private MyLogger logger;

    public FrameworkLoggerAdapter(MyLogger logger) {
        this.logger = logger;
    }

    @Override
    public void log(String message) {
        this.logger.logMessage(message);
    }

    @Override
    public void log(Throwable exception) {
        this.logger.logException(exception);
    }
}

FrameworkLoggerインターフェイスを実装し、 MyLogger実装を受け入れるアダプタクラスを定義することによって、異なるインターフェイス間で機能をマッピングできます。これで、 MyLoggerすべての実装でBluetoothManagerを使用することができます。

FrameworkLogger fileLogger = new FrameworkLoggerAdapter(new MyFileLogger());
BluetoothManager manager = new BluetoothManager(fileLogger);

FrameworkLogger consoleLogger = new FrameworkLoggerAdapter(new MyConsoleLogger());
BluetoothManager manager2 = new BluetoothManager(consoleLogger);

Javaの例

Adapterパターンの素晴らしい既存の例は、SWTで見つけることができるのMouseListenerMouseAdapterのクラス。

MouseListenerインタフェースは次のようになります。

public interface MouseListener extends SWTEventListener {
    public void mouseDoubleClick(MouseEvent e);
    public void mouseDown(MouseEvent e);
    public void mouseUp(MouseEvent e);
}

ここで、UIを構築してこれらのリスナーを追加するシナリオを想像してください。しかし、何かがシングルクリックされたとき(mouseUp)以外のことは気にしません。あなたは空の実装を絶えず作成したくないでしょう:

obj.addMouseListener(new MouseListener() {

    @Override
    public void mouseDoubleClick(MouseEvent e) {
    }

    @Override
    public void mouseDown(MouseEvent e) {
    }

    @Override
    public void mouseUp(MouseEvent e) {
        // Do the things
    }

});

代わりに、MouseAdapterを使用することができます:

public abstract class MouseAdapter implements MouseListener {
    public void mouseDoubleClick(MouseEvent e) { }
    public void mouseDown(MouseEvent e) { }
    public void mouseUp(MouseEvent e) { }
}

空のデフォルトの実装を提供することで、私たちがアダプタから気にかけているメソッドだけを自由にオーバーライドすることができます。上記の例から、

obj.addMouseListener(new MouseAdapter() {

    @Override
    public void mouseUp(MouseEvent e) {
        // Do the things
    }

});

アダプタ(UMLとその例)

より多くの想像力を持たせることができるときにアダプターパターンと状況の種類を使用するために、ここでは小さく、シンプルで非常に具体的な例を示します。ここにはコードはなく、UMLだけでなく、例の状況とその問題の説明もあります。確かに、UMLコンテンツはJavaのように書かれています。 (ヒントテキストには「良い例はほとんどがコードです」と書かれていますが、デザインパターンは抽象的で、別の方法でも導入できると思います)。

通常、アダプタパターンは、互換性のないインターフェイスがあり、そのいずれも直接書き換えることができない状況に適したソリューションです。

素敵な小さなピザ宅配サービスを行っているとします。顧客はあなたのウェブサイトでオンラインで注文することができますし、クラスPizzaを使用して小規模なシステムを持ち、 Pizzaを表現し、請求書、税務レポートなどを計算します。あなたのピザの価格は、(あなたが選んだ通貨の)セントで価格を表す単一の整数として与えられます。

ここに画像の説明を入力

あなたのデリバリーサービスはすごくうまくいっていますが、ある時点では、あなた自身の顧客の増加に対応することはできませんが、まだ拡大したいと考えています。大きなオンラインのメタデリバリーサービスのメニューにピザを追加することにしました。彼らはピザだけでなく多くの異なる食事を提供しているので、彼らのシステムは抽象化をより多く使用し、お金を表すクラスMoneyAmountと共に食事を表すインターフェースIMealを持っています。

ここに画像の説明を入力

MoneyAmountは入力として2つの整数で構成され、1つはコンマの前の金額(またはランダムな通貨)で、もう1つはコンマの後の0から99までのセントの金額です。

ここに画像の説明を入力

Pizzaの価格は合計価格をセント(> 99)の額として表す単一の整数であるため、 IMeal互換性はありません。これは、アダプターパターンが出現するポイントです。自分のシステムを変更したり、新しいシステムを作成するのに多大な労力を要し、互換性のないインターフェースを実装する必要がある場合は、アダプターpattternを適用することができます。

パターンを適用するには、クラスアダプタとオブジェクトアダプタの2つの方法があります。

両方とも、アダプター( PizzaAdapter )は、新しいインターフェースとアダプター(この例ではPizza )の間で何らかのPizzaAdapterとして機能するという共通点があります。アダプターは新しいインターフェース( IMeal )を実装し、次にPizzaを継承し、独自の価格を1つの整数から2(クラス・アダプター)に変換します。

ここに画像の説明を入力

または属性としてPizza型のオブジェクトを持ち、その値(オブジェクトアダプタ)を変換します。

ここに画像の説明を入力

アダプターパターンを適用すると、互換性のないインターフェース間で「翻訳」することになります。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow