Skeleton of GOF's Design Pattern


BRIDGEの骸骨

BRIDGE

抽出クラスと実装を分離するパターンです。
このパターンを利用して、実装依存部分を分離すれば、アプリケーション固有の設計抽象度を向上させることができます。

言いかえれば、フレームワークの実装に依存する部分を局所化することによって、アプリケーションの基本設計部分への影響を低減させることができます。

『BRIDGEの骸骨』では、Abstraction クラスのサブクラス定義を省略しています。


■ 『BRIDGEの骸骨』の構造


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

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

import java.awt.*;
public class BridgeSample {
    static public void main(String[] args) { 
       Abstraction abstraction = new Abstraction("A");
       abstraction.Operation();

       abstraction = new Abstraction("B"); 
       abstraction.Operation();
    } 
}

class Abstraction {
    private Implementor _imp = null;
    public Abstraction(String sw) {
        if (sw.equals("A")) {
            _imp = new ImplementorA();
        } else if (sw.equals("B")) {
            _imp = new ImplementorB();
        }
    }
    public void Operation() { 
        _imp.OperationImp(); 
    }
}

abstract class Implementor { 
    abstract public void OperationImp();
}

class ImplementorA extends Implementor { 
    public void OperationImp() { 
        System.out.println("Call ImplementorA::OperationImp()");
    }
}

class ImplementorB extends Implementor { 
    private Frame _frame = new Frame("BridgeSample"); 
    public void OperationImp() { 
        _frame.add(new Label("Call ImplementorB::OperationImp()", Label.CENTER));
        _frame.setSize(250, 100);
        _frame.show(); 
    }
}

○ C++版
// Copyright(C) 2003 Yoshinori Oota All rights reserved.
#include <windows.h>
#include <iostream>
using namespace std;

class Implementor {
public:
    Implementor();
    virtual ~Implementor();
    virtual void OperationImp() const = 0;
};

class ImplementorA : public Implementor {
public:
    ImplementorA();
    virtual ~ImplementorA();
    virtual void OperationImp() const;
};

class ImplementorB : public Implementor {
public:
    ImplementorB();
    virtual ~ImplementorB();
    virtual void OperationImp() const;
};

class Abstraction {
public:
    Abstraction(char sw);
    virtual ~Abstraction();
    virtual void Operation() const;  // 継承を考慮し仮想関数としておく
protected:
    Implementor* imp_;
};


Implementor::Implementor() { }
Implementor::~Implementor() { }

ImplementorA::ImplementorA() { }
ImplementorA::~ImplementorA() { }
void ImplementorA::OperationImp() const {
    cout << "Call ImplementorA::OperationImp()" << endl;
}

ImplementorB::ImplementorB() { }
ImplementorB::~ImplementorB() { }
void ImplementorB::OperationImp() const {
    MessageBox(0, "Call ImplementorB::OperationImp", "AdapterSample", MB_OK|MB_SETFOREGROUND);
}


Abstraction::Abstraction(char sw) : imp_(NULL) {
    if (sw == 'A') {
        imp_ = new ImplementorA();
    } else if (sw == 'B') {
        imp_ = new ImplementorB();
    }    
}
Abstraction::~Abstraction() {
    delete imp_;
}
void Abstraction::Operation() const {
    imp_->OperationImp();
}


int main() {
    Abstraction* abstraction = new Abstraction('A');
    abstraction->Operation();
    delete abstraction;

    abstraction = new Abstraction('B');
    abstraction->Operation();
    delete abstraction;

    return 0;
}

○ C版
/* Copyright(C) 2009 Yoshinori Oota All rights reserved. */
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
enum COMPONENT_TYPE { CLASS_A ,CLASS_B };

/* Implementor Interface */
struct Implementor {
    void (*OperationImp)();
};
struct Implementor* New_Implementor (enum CLASS_TYPE type);
void Delete_Implementor(struct Implementor* implementor);
void ImplementorA_OperationImp();
void ImplementorB_OperationImp();

/* Abstraction Interface */
struct Abstraction {
    struct Implementor* imp_;
    void (*Operation)(struct Abstraction* pthis);
};
struct Abstraction* New_Abstraction(enum CLASS_TYPE type);
void Delete_Abstraction(struct Abstraction* abs); 
void Abstraction_Operation(struct Abstraction* abs);

/* Implementor Class Implementation */
struct Implementor* New_Implementor(enum CLASS_TYPE type) {
    struct Implementor* implementor = NULL;
    implementor = (struct Implementor*)malloc(sizeof(struct Implementor));
    switch(type) {
    case CLASS_A:
        implementor->OperationImp = &ImplementorA_OperationImp;
        break;
    case CLASS_B:
        implementor->OperationImp = &ImplementorB_OperationImp;
        break;
    }
    return implementor;
}

void Delete_Implementor(struct Implementor* implementor) {
    if (implementor != NULL) {
        return;
    }
    free(implementor);
    implementor = NULL;
    return;
}


void ImplementorA_OperationImp() {
    printf("Call ImplementorA::OperationImp\n");
    return;
}

void ImplementorB_OperationImp() {
    MessageBox(0, "Call ImplementorB::OperationImp\n", "Bridge Sample", MB_OK|MB_SETFOREGROUND);
    return;
}

/* Abstraction Class Implementation */
struct Abstraction* New_Abstraction(enum CLASS_TYPE type) {
    struct Abstraction* abstraction = NULL;

    abstraction = (struct Abstraction*)malloc(sizeof(struct Abstraction));
    abstraction->Operation = &Abstraction_Operation;
    abstraction->imp_ = New_Implementor(type);
    return abstraction;
}

void Delete_Abstraction(struct Abstraction* abstraction) {
    if (abstraction != NULL) {
        return;
    }
    Delete_Implementor(abstraction->imp_);
    free(abstraction);
    abstraction = NULL;
    return;
}

void Abstraction_Operation(struct Abstraction* pthis) {
    pthis->imp_->OperationImp();
    return;
}


int main() {
    struct Abstraction* abstraction = NULL;

    abstraction = New_Abstraction(CLASS_A);
    abstraction->Operation(abstraction);
    Delete_Abstraction(abstraction);

    abstraction = New_Abstraction(CLASS_B);
    abstraction->Operation(abstraction);
    Delete_Abstraction(abstraction);

    return 0;
}


改訂履歴

2004.11.20 鳥の夢さんのご指摘により、C++のAbstractionクラスのデストラクタでimp_のdelete忘れを修正
  2009.2.21 C言語版を追加
     

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

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

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