Skeleton of GOF's Design Pattern


ADAPTERの骸骨

Adapter

まったくインターフェースに互換性のないクラス同士を組み合わせるためのパターンです。

クライアントコードを変えずに機能拡張するのが、このパターンの目的です。クライアントコードで利用されている クラスA(Target) に、クラスB(Adaptee)の機能を使ってクラスA を 機能拡張したい場合に用います。

ADAPTER では、クラスA クラスA’(Adapter) として拡張し、クラスA’(Adapter) から クラスB (Adaptee) の機能を使います。

このとき、クライアントコードに、クラスA’ (Adapter)をクラスA(Target)として渡してやれば、表面上、クラスAからクラスBの機能が使えるようになります。これをインターフェース適合とよびます。

言葉で表現すると、ややこしいので、右図を見てください。

ADAPTER の本質は、オーバーライドです。クラスAOperationA() から クラスB OperationB() を呼び出すために、メソッドをサブクラスでオーバーライドするのがテクニックの基本です。

しかし、C++では、あらかじめターゲットとなるメソッド(ここでは、ClassA::OperationA)が仮想関数宣言されているかどうかが問題となります。


■ 『ADAPTERの骸骨』の構造


■ 『ADAPTERの骸骨』 プログラム・コード

□ Java2版
// Copyright(C) 2000-2003 Yoshinori Oota All rights reserved.

import java.awt.*;

public class AdapterSample {
    static public Target Create(String str) {
        if (str.equals("Target")) {
            return new Target();
        } else if (str.equals("Adapter")) {
            return new Adapter();
        }
        return null;
    }

    static public void main(String[] args) { 
        Target target1 = Create("Target");
        Target target2 = Create("Adapter"); // クライアントへは Target として渡す
		
        target1.Operation();
        target2.Operation();  // Target に新しい振舞いを定義できた!
    }
}

	
class Target { 
    public void Operation() { 
        System.out.println("Hello Design Pattern"); 
    } 
}

class Adapter extends Target {
    private Frame _adaptee = new Frame("AdapterSample");
    public void Operation() { 
        _adaptee.add(new Label("Hello Design Pattern", Label.CENTER));
        _adaptee.setSize(150, 100);
        _adaptee.show();
    } 
}

○ C++版
// Copyright(C) 2003 Yoshinori Oota All rights reserved.

#include <iostream>
#include <windows.h>
using namespace std;

class Target {
public:
    Target();
    virtual ~Target();
    virtual void Operation() const;  // C++ では、virtual が必要なのが玉に傷
};

class Adapter : public Target {
public:
    Adapter();
    virtual ~Adapter();
    virtual void Operation() const;
};


Target::Target() { }
Target::~Target() { }
void Target::Operation() const {
    cout << "Hello Design Pattern" << endl;
}

Adapter::Adapter() { }
Adapter::~Adapter() { }
void Adapter::Operation() const {
    // クラスじゃないけど、Adaptee
    MessageBox(0, "Hello Design Pattern", "AdapterSample", MB_OK|MB_SETFOREGROUND);
}
Target* Create(const string& sw) {
    if (sw == "Target") {
        return new Target();
    } else if (sw == "Adapter") {
        return new Adapter();
    }
}

int main() {
    Target* target1 = Create("Target");
    Target* target2 = Create("Adapter");

    target1->Operation();
    target2->Operation();

    delete target1;
    delete target2;

    return 0;
}

○ C版
/* Copyright(C) 2009 Yoshinori Oota All rights reserved. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
/* Target Interface */
struct Target {
    void (*Operation)();
};
struct Target* New_Target();
void Delete_Target(struct Target* target);
void Target_Operation();

/* Adapter Interface */
struct Target* New_Adapter();
void Adapter_Operation();

/* Target Class Implementation */
struct Target* New_Target() {
    struct Target* target = NULL;
    target = (struct Target*)malloc(sizeof(struct Target));
    target->Operation = &Target_Operation;
    return target;
}

void Delete_Target(struct Target* target) {
    if (target == NULL) {
        return;
    }
    free(target);
    target = NULL;
    return;
}

void Target_Operation() {
    printf("Hello Design Pattern\n");
    return;
}

/* Adapter Class Implementation */
struct Target* New_Adapter() {
    struct Target* target = NULL;
    target = New_Target();
    target->Operation = &Adapter_Operation; // override
    return target;
}

void Adapter_Operation() {
    /* クラスじゃないけど、Adaptee */
    MessageBox(0 ,"Hello Design Pattern" ,"Adapter Sample" ,MB_OK|MB_SETFOREGROUND);
    return;
}

struct Target* Create(const char* sw) {
    if (strcmp(sw ,"Target") == 0) {
        return New_Target();
    } else if (strcmp(sw ,"Adapter") == 0) {
        return New_Adapter();
    }
    return NULL;
}

int main() {
    struct Target* target1 = NULL;
    struct Target* target2 = NULL;

    target1 = Create("Target");
    target2 = Create("Adapter");

    target1->Operation();
    target2->Operation();

    Delete_Target(target1);
    Delete_Target(target2);

    return 0;
}


改訂履歴

2009.2.21 C言語版を追加
     
     

ご意見、ご感想はこちらまで。

Copyright(C) 2000-2009 Yoshinori Oota All rights reserved.

本ホームページのリンクは自由です。複製、転載される場合は、必ず著者までご連絡をください。