Skeleton of GOF's Design Pattern


CHAIN OF RESPONSIBILITYの骸骨

CHAIN OF RESPONSIBILITY

オブジェクトを数珠つなぎにし、クライアントの要求の処理が終わるまで、処理を横流しにするパターンです。

このパターンは、フィルタ処理や、イベントなどの処理に用いることができます。 イベントメッセージの解釈の処理に、このパターンを用いれば、複雑な条件分岐をなくすことができ、また処理単位をカプセル化できるため、コードの可読性、保守性が高まります。

条件分岐の処理としては、STRATEGY パターンがマップ型なのに対し、CHAIN OF RESPONSIBILITY は、リスト型になります。


■ 『CHAIN OF RESPONSIBILITYの骸骨』の構造


■ 『CHAIN OF RESPONSIBILITYの骸骨』の特徴的な協調関係


■ 『CHAIN OF RESPONSIBILITYの骸骨』 プログラム・コード

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

public class ChainOfResponsibilitySample {
    static ChainOfResponsibility makeChain() {
        return new Extend1Chain(
                    new Extend2Chain( 
                        new Extend3Chain(null))); 
    }
    static public void main(String[] args) {
       ChainOfResponsibility chain = makeChain();
       chain.Handle(2); 
    } 
}

abstract class ChainOfResponsibility { 
    private ChainOfResponsibility _successor = null;
    ChainOfResponsibility(ChainOfResponsibility chain) {
        _successor = chain;
    }
    protected void Next(int i) { 
        if (_successor != null) { 
            _successor.Handle(i); 
        }
    } 
    abstract public void Handle(int i);
}

class Extend1Chain extends ChainOfResponsibility { 
    Extend1Chain(ChainOfResponsibility chain) {
        super(chain);
    }
    public void Handle(int i) { 
        if (i == 1) { 
            System.out.println("Extend1 gotta Message!"); 
        } else { 
            Next(i); 
        } 
    } 
}

class Extend2Chain extends ChainOfResponsibility { 
    public Extend2Chain(ChainOfResponsibility chain) { 
        super(chain); 
    }
    public void Handle(int i) { 
        if (i == 2) { 
            System.out.println("Extend2 gotta Message!"); 
        } else { 
            Next(i); 
        } 
    } 
}

class Extend3Chain extends ChainOfResponsibility { 
    public Extend3Chain(ChainOfResponsibility chain) { 
        super(chain); 
    }
    public void Handle(int i) { 
        if (i == 3) { 
            System.out.println("Extend3 gotta Message!"); 
        } else { 
            Next(i); 
        } 
    } 
}

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

#include <iostream>
using namespace std;

class ChainOfResponsibility {
public:
    ChainOfResponsibility(ChainOfResponsibility* chain);
    virtual ~ChainOfResponsibility();
    virtual void Handle(int i) = 0;
protected:
    virtual void Next(int i);
private:
    ChainOfResponsibility* successor_;
};

class Extend1Chain : public ChainOfResponsibility {
public:
    Extend1Chain(ChainOfResponsibility* chain);
    virtual ~Extend1Chain();
    virtual void Handle(int i);
};

class Extend2Chain : public ChainOfResponsibility {
public:
    Extend2Chain(ChainOfResponsibility* chain);
    virtual ~Extend2Chain();
    virtual void Handle(int i);
};

class Extend3Chain : public ChainOfResponsibility {
public:
    Extend3Chain(ChainOfResponsibility* chain);
    virtual ~Extend3Chain();
    virtual void Handle(int i);
};


ChainOfResponsibility::ChainOfResponsibility(ChainOfResponsibility* chain) :
  successor_(chain) { }
ChainOfResponsibility::~ChainOfResponsibility() {  delete successor_;  }
void ChainOfResponsibility::Next(int i) {
    if (successor_ != NULL) {
        successor_->Handle(i);
    }
}

Extend1Chain::Extend1Chain(ChainOfResponsibility* chain) :
  ChainOfResponsibility(chain) { }
Extend1Chain::~Extend1Chain() { }
void Extend1Chain::Handle(int i) {
    if (i == 1) {
        cout << "Extend1 gotta Message!" << endl;
    } else {
        Next(i);
    }
}

Extend2Chain::Extend2Chain(ChainOfResponsibility* chain) :
  ChainOfResponsibility(chain) { }
Extend2Chain::~Extend2Chain() { }
void Extend2Chain::Handle(int i) {
    if (i == 2) {
        cout << "Extend2 gotta Message!" << endl;
    } else {
        Next(i);
    }
}

Extend3Chain::Extend3Chain(ChainOfResponsibility* chain) :
  ChainOfResponsibility(chain) { }
Extend3Chain::~Extend3Chain() { }
void Extend3Chain::Handle(int i) {
    if (i == 3) {
        cout << "Extend3 gotta Message!" << endl;
    } else {
        Next(i);
    }
}


ChainOfResponsibility* makeChain() {
    return new Extend1Chain(
               new Extend2Chain(
                   new Extend3Chain(NULL)));
}

int main() {
    ChainOfResponsibility* chain = makeChain();
    chain->Handle(2);
    delete chain;
    return 0;
}

○ C版
/* Copyright(C) 2009 Yoshinori Oota All rights reserved. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum CLASS_TYPE { EXTEND1 ,EXTEND2 ,EXTEND3 };

/* ChainOfResponsibility Interface */
struct ChainOfResponsibility {
    struct ChainOfResponsibility* successor_;
    void (*Next)(struct ChainOfResponsibility* pthis ,int i);
    void (*Handle)(struct ChainOfResponsibility* pthis ,int i); 
};
struct ChainOfResponsibility* New_ChainOfResponsibility(struct ChainOfResponsibility* scr 
    ,enum CLASS_TYPE type);
void Delete_ChainOfResponsibility(struct ChainOfResponsibility* chain);
void ChainOfResponsibility_Next(struct ChainOfResponsibility* pthis ,int i);
void Extend1Chain_Handle(struct ChainOfResponsibility* pthis ,int i);
void Extend2Chain_Handle(struct ChainOfResponsibility* pthis ,int i); 
void Extend3Chain_Handle(struct ChainOfResponsibility* pthis ,int i);

/* ChainOfResponsibility Class Implemenation */
struct ChainOfResponsibility* New_ChainOfResponsibility(struct ChainOfResponsibility* scr 
    ,enum CLASS_TYPE type) 
{
    struct ChainOfResponsibility* chain = NULL;
    chain = (struct ChainOfResponsibility*)malloc(sizeof(struct ChainOfResponsibility));
    chain->Next = &ChainOfResponsibility_Next;
    switch (type) {
    case EXTEND1:
        chain->Handle = &Extend1Chain_Handle;
        break;
    case EXTEND2:
        chain->Handle = &Extend2Chain_Handle;
        break;
    case EXTEND3:
        chain->Handle = &Extend3Chain_Handle;
        break;
    }
    chain->successor_ = scr;
    return chain;
}

void Delete_ChainOfResponsibility(struct ChainOfResponsibility* chain) {
    if (chain == NULL) {
        return;
    }
    if (chain->successor_ != NULL) {
        Delete_ChainOfResponsibility(chain->successor_);
    }
    free(chain);
    chain = NULL;
    return;
}

void ChainOfResponsibility_Next (struct ChainOfResponsibility* pthis ,int i) {
    if (pthis->successor_ != NULL) {
        pthis->successor_->Handle(pthis->successor_ ,i); 
    }
    return;
}

void Extend1Chain_Handle(struct ChainOfResponsibility* pthis ,int i) {
    if (i == 1) {
        printf("Extend1 gotta Message!\n");
    } else { 
        pthis->Next(pthis ,i);
    }
    return;
}

void Extend2Chain_Handle(struct ChainOfResponsibility* pthis ,int i) {
    if (i == 2) {
        printf("Extend2 gotta Message!\n");
    } else {
        pthis->Next(pthis ,i);
    }
    return;
}

void Extend3Chain_Handle(struct ChainOfResponsibility* pthis ,int i) {
    if (i == 3) {
        printf("Extend3 gotta Message!\n");
    } else {
        pthis->Next(pthis ,i);
    }
    return;
}


int main() {
    struct ChainOfResponsibility* chain = NULL;
    chain = New_ChainOfResponsibility(NULL ,EXTEND3);
    chain = New_ChainOfResponsibility(chain ,EXTEND2);
    chain = New_ChainOfResponsibility(chain ,EXTEND1);

    chain->Handle(chain ,2);

    Delete_ChainOfResponsibility(chain);

    return 0;
}


改訂履歴

2009.2.22 C言語版を追加
     
     

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

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

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