Skeleton of GOF's Design Pattern for Beginer


COMPOSITEの骸骨

COMPOSITE

オブジェクトの木構造を実現するためのパターンです。

このパターンの特徴は、木構造に構成されたオブジェクトも、単一のオブジェクトも同様に扱うことができることです。COMPOSITE の代表例としては、DOM が挙げられます。

デザインパターンの代表選手です。デザインパターンを理解するためには、この COMPOSITE パターンを理解することから始めるのがよいでしょう。

具体的な例を知りたい方は、COMPOSITE で DOM もどきにチャレンジ!を参照してください。


■ 『COMPOSITEの骸骨』の構造


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

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

import java.util.*;

public class CompositeSample {
    static public Component makeComposite() {
        // 以下のような構造を作る
        //   Composite -+- Leaf   
        //              +- Leaf   
        //              +- Composite -+- Leaf 
        //                            +- Leaf 
        Composite composite1 = new Composite();
        composite1.add(new Leaf());
        composite1.add(new Leaf());

        Component composite2 = new Composite();
        composite2.add(new Leaf());
        composite2.add(new Leaf());
        composite2.add(composite1);
        return composite2;
    }

    static public void main(String[] args) {
        Component component = makeComposite();
        component.Operation(0); 
    } 
}

abstract class Component {
    abstract public void Operation(int n);
    public void indent(int n) {
        while (n != 0) {
            System.out.print("    ");
            --n;
        }
    }
}

class Leaf extends Component { 
    public void Operation(int n) {
        indent(n);
        System.out.println("- Leaf"); 
    }
}

class Composite extends Component { 
    private LinkedList _children = new LinkedList();
    public void Operation(int n) { 
        indent(n);
        System.out.println("+ Composite");
        ListIterator componentList = _children.listIterator();
        while (componentList.hasNext()) { 
            Component child = (Component)componentList.next();
            ++n;
            child.Operation(n); 
            --n;
        } 
    } 
    public void add(Component component) { 
        _children.add(component); 
    } 
}

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

#include <list>
#include <iostream>
using namespace std;

class Component {
public:
    Component();
    virtual ~Component();
    virtual void Operation(int n) const = 0;
    void indent(int n) const;
};

class Leaf : public Component {
public:
    Leaf();
    virtual ~Leaf();
    virtual void Operation(int n) const;
};

class Composite : public Component {
public:
    Composite() { }
    virtual ~Composite();
    virtual void Operation(int n) const;
    void add(Component* c);
private:
    list<Component*> children_;    
};

Component::Component() { }
Component::~Component() { }
void Component::indent(int n) const {
    while (n != 0) {
        cout << "    ";
        --n;
    }
}

Leaf::Leaf() { }
Leaf::~Leaf() { }
void Leaf::Operation(int n) const {
    indent(n);
    cout << "- Leaf" << endl;
}


Composite::Composite() { }
Composite::~Composite() {
    list<Component*>::iterator it = children_.begin();
    while (it != children_.end()) {
        delete (*it);
        ++it;
    }
}
void Composite::Operation(int n) const {
    indent(n);
    cout << "+ Composite" << endl;
    list<Component*>::const_iterator it = children_.begin(); 
    while (it != children_.end()) {
        ++n;
        (*it)->Operation(n);
        --n;
        ++it;
    }
}
void Composite::add(Component* c) {
    children_.push_back(c);
}


Component* makeComposite() {
    // 以下のような構造を作る
    //   Composite -+- Leaf   
    //              +- Leaf   
    //              +- Composite -+- Leaf 
    //                            +- Leaf 
    Composite* composite1 = new Composite();
    composite1->add(new Leaf());
    composite1->add(new Leaf());

    Composite* composite2 = new Composite();
    composite2->add(new Leaf());
    composite2->add(new Leaf());
    composite2->add(composite1);
    return composite2;
}

int main() {
    Component* component = makeComposite();
    component->Operation(0);
    delete component;

    return 0;
}

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

struct Component;
void indent(int n);

/* Component List */
struct ComponentList {
    struct Component* component_;
    struct ComponentList* next_;
};
struct ComponentList* New_ComponentList(struct Component* component);
void Delete_ComponentList(struct ComponentList* list);

/* Component Interface */
struct Component {
    enum COMPONENT_TYPE type_;
    struct ComponentList* child_top_;
    struct ComponentList* child_last_;
    void (*add)(struct Component* pthis ,struct Component* child);
    void (*Operation)(struct Component* pthis ,int n);
};
struct Component* New_Component(enum COMPONENT_TYPE type); 
void Delete_Component(struct Component* component);
void Leaf_Operation(struct Component* pthis ,int n);
void Leaf_add(struct Component* pthis, struct Component* child);
void Composite_Operation(struct Component* pthis ,int n);
void Composite_add(struct Component* pthis ,struct Component* child); 

/* ComponentList Implementation */
struct ComponentList* New_ComponentList(struct Component* component) {
    struct ComponentList* list = NULL;
    list = (struct ComponentList*)malloc(sizeof(struct ComponentList));
    list->component_ = component;
    list->next_ = NULL;
    return list;
}

void Delete_ComponentList(struct ComponentList* list) {
    struct ComponentList* tmp = NULL;
    if (list == NULL) {
        return;
    }
    while (list != NULL) {
        tmp = list->next_;
        free(list);
        list = tmp;
    }
    return;
}

/* Component Class Implementation */
struct Component* New_Component(enum COMPONENT_TYPE type) {
    struct Component* component = NULL;
    component = (struct Component*)malloc(sizeof(struct Component));
    component->type_ = type;
    component->child_top_ = NULL;
    component->child_last_ = NULL;
    switch (type) {
    case LEAF:
        component->add = &Leaf_add;
        component->Operation = &Leaf_Operation;
        break;
    case COMPOSITE:
        component->add = &Composite_add;
        component->Operation = &Composite_Operation;
        break;
    }
    return component;
}

void Delete_Component(struct Component* component) {
    struct ComponentList* cur = NULL;
    struct ComponentList* tmp = NULL;

    if (component == NULL) {
        return;
    }

    if (component->type_ == COMPOSITE) {
        struct ComponentList* cur = NULL;
        cur = component->child_top_;
        while (cur != NULL) {
            Delete_Component(cur->component_);
            cur = cur->next_;
        }
        Delete_ComponentList(component->child_top_);
    }
    free(component);
    component = NULL;
    return;
}

void Leaf_add(struct Component* pthis ,struct Component* child) {
    return; /* No operation */
}

void Leaf_Operation(struct Component* pthis ,int n) {
    indent(n);
    printf("- Leaf\n");
    return;
}

void Composite_add(struct Component* pthis ,struct Component* child) {
    struct Component* cur = NULL;
    struct ComponentList* list = NULL;
    list = (struct ComponentList*)malloc(sizeof(struct ComponentList));
    list->component_ = child;
    list->next_ = NULL;
    if (pthis->child_top_ == NULL) {
        pthis->child_top_ = list;
        pthis->child_last_ = list;
    } else {
        pthis->child_last_->next_ = list;
        pthis->child_last_ = list;
    }
    return;
}

void Composite_Operation(struct Component* pthis ,int n) {
    struct Component* component = NULL;
    struct ComponentList* cur = NULL;
    indent(n);
    printf("+ Composite\n");
    cur = pthis->child_top_;
    while (cur != NULL) {
        ++n;
        component = cur->component_;
        component->Operation(component, n);
        --n;
        cur = cur->next_;
    }
    return;
}

void indent(int n) {
    while (n != 0) {
        printf("    ");
        --n;
    }
    return;
}

struct Component* makeComposite() {
    /* 以下のような構造を作る
     *   Composite -+- Leaf   
     *              +- Leaf   
     *              +- Composite -+- Leaf 
     *                            +- Leaf */
    struct Component* composite1 = NULL;
    struct Component* composite2 = NULL;

    composite1 = New_Component(COMPOSITE);
    composite1->add(composite1 ,New_Component(LEAF));
    composite1->add(composite1 ,New_Component(LEAF));

    composite2 = New_Component(COMPOSITE);
    composite2->add(composite2 ,New_Component(LEAF));
    composite2->add(composite2 ,New_Component(LEAF));
    composite2->add(composite2 ,composite1);

    return composite2;
}

int main() {
    struct Component* component = NULL;

    component = makeComposite();
    component->Operation(component ,0);

    Delete_Component(component);
    return 0;
}


改訂履歴

2005.2.25 デザインパターンの塗り薬へのリンクを追加
  2009.2.21 C言語版を追加
     

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

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

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