Skeleton of GOF's Design Pattern


BUILDERの骸骨

BUILDER

オブジェクトの生成手順を生成手段と分離するためのパターンです。

例えば、フィルタやオブジェクトツリーの生成など、目的に応じて生成手順を変更しなければならない場合があります。そのような場合、このパターンを用います。Director は、生成手順を知っているクラスであり、Builder はオブジェクトを生成するクラスです。Director は用途に応じて定義され、Builder を利用します。


■ 『BUILDERの骸骨』の構造


■ 『BUILDERの骸骨』の特徴的な協調関係


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

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

import java.util.*;

public class BuilderSample {
    static public void main(String[] args) { 
        Director director = new Director();
        Builder builder = new Builder();
        director.Construct(builder);
        Component tree = builder.GetResult();
        tree.print(0); 
    } 
}

class Director { 
    public void Construct(Builder builder) {
        // 次のような Composite構造を生成する
        // Composite("Root") -+- Leaf("L1")
        //                    +- Leaf("L2")
        //                    +- Composite("A") -+-Leaf("L3")
        //                                       +-Leaf("L4")
        builder.BuildLeaf("L1");
        builder.BuildLeaf("L2");
        builder.BuildComposite("A");
        builder.ChangeCurrent("A");
        builder.BuildLeaf("L3");
        builder.BuildLeaf("L4");
    } 
}

class Builder { 
    private Composite _root = new Composite("Root");
    private Composite _curComposite = _root;
    public void BuildLeaf(String id) {
        _curComposite.add(new Leaf(id));
    }
    public void BuildComposite(String id) { 
        _curComposite.add(new Composite(id)); 
    }
    public void ChangeCurrent(String id) { 
        _curComposite = (Composite)_curComposite.getComponentById(id); 
    } 
    public Component GetResult() {
        return _root;
    }
}

abstract class Component {
    private String _name = null;
    public Component(String id) {
        _name = id;
    }
    public String getName() {
        return _name;
    }
    protected void indent(int ind) {
        for (int i = 0; i < ind; ++i) {
            System.out.print("    ");
        }
    }
    abstract public void print(int n);
}

class Leaf extends Component {
    public Leaf(String id) {
        super(id);
    }
    public void print(int n) {
        indent(n);
        System.out.println("- Leaf(" + getName() +")");
    }
}

class Composite extends Component {
    private HashMap _children = new HashMap();
    public Composite(String id) {
        super(id);
    }
    public void add(Component component) {
        _children.put(component.getName(), component);
    }
    public Component getComponentById(String id) {
        return (Component)_children.get(id);
    }
    public void print(int n) {
        indent(nd;
        System.out.println("+ Composite(" + getName() +")");
        Set keySet = _children.keySet();
        Iterator it = keySet.iterator();
        while (it.hasNext()) {
            String name = (String)it.next();
            Component c = (Component)_childs.get(name);
            ++n;
            c.print(n);
            --n;
        }
    }
}

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

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

class Builder;
class Component;
class Composite;

class Director { 
public:
    Director();
    ~Director();
    void Construct(Builder* builder);
};

class Builder { 
public:
    Builder();
    ~Builder();
    Component* GetResult();
protected:
    friend class Director;
    void BuildLeaf(const string& id);
    void BuildComposite(const string& id);
    void ChangeCurrent(const string& id);
private:
    Composite* root_;
    Composite* curComposite_;
};


class Component {
public:
    Component(const string& id);
    virtual ~Component();
    virtual void print(int ind) = 0;
    const string& getName() const;
protected:
    void indent(int ind);
private:
    string name_;
};

class Leaf : public Component {
public:
    Leaf(const string& id);
    virtual ~Leaf();
    virtual void print(int ind);
};

class Composite : public Component {
public:
    Composite(const string& id);
    virtual ~Composite();
    virtual void print(int ind);
    void add(Component* component);
    Component* getComponentById(const string& id);    
private:
    map<string, Component*> children_;
};


Director::Director() { }
Director::~Director() { }
void Director::Construct(Builder* builder) {
    // 次のような Composite構造を生成する
    // Composite("Root") -+- Leaf("L1")
    //                    +- Leaf("L2")
    //                    +- Composite("A") -+-Leaf("L3")
    //                                       +-Leaf("L4")
    builder->BuildLeaf("L1");
    builder->BuildLeaf("L2");
    builder->BuildComposite("A");
    builder->ChangeCurrent("A");
    builder->BuildLeaf("L3");
    builder->BuildLeaf("L4");
}


Builder::Builder() : root_(new Composite("Root")), curComposite_(root_) { }
Builder::~Builder() { }
void Builder::BuildLeaf(const string& id) {
    curComposite_->add(new Leaf(id));
}
void Builder::BuildComposite(const string& id) { 
    curComposite_->add(new Composite(id)); 
}
void Builder::ChangeCurrent(const string& id) { 
    curComposite_ = (Composite*)curComposite_->getComponentById(id); 
} 
Component* Builder::GetResult() {
    return root_;
}


Component::Component(const string& id) : name_(id) { }
Component::~Component() { }
const string& Component::getName() const {
    return name_;
}
void Component::indent(int n) {
    for (int i = 0; i < n; ++i) {
        cout << "    ";
    }
}

Leaf::Leaf(const string& id) : Component(id) { }
Leaf::~Leaf() { }
void Leaf::print(int n) {
    indent(n);
    cout << "- Leaf(" << getName() << ")" << endl;
}

Composite::Composite(const string& id) : Component(id) { }
Composite::~Composite() {
    map<string, Component*>::iterator it = children_.begin();
    while (it != children_.end()) {
        delete (*it).second;
        ++it;
    }
}
void Composite::add(Component* component) {
    children_[component->getName()] = component;
}
Component* Composite::getComponentById(const string& id) {
    map<string, Component*>::iterator it = children_.find(id);
    return it != children_.end() ? (*it).second : NULL;
}
void Composite::print(int n) {
    indent(n);
    cout << "+ Composite(" << getName() << ")" << endl;
    map<string, Component*>::iterator it = children_.begin();
    while (it != children_.end()) {
        ++n;
        (*it).second->print(n);
        --n;
        ++it;
    }
}


int main() {
    Director director;
    Builder* builder = new Builder();
    director.Construct(builder);
    Component* tree = builder->GetResult();
    tree->print(0); 

    delete builder;
    delete tree;

    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);

/* ComponentList */
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 {
    char* id_;
    enum COMPONENT_TYPE type_;
    struct ComponentList* child_top_;
    struct ComponentList* child_last_;
    void (*add)(struct Component* pthis, struct Component* child);
    void (*print)(struct Component* pthis, int n);
    struct Component* (*getComponentById)(struct Component* pthis, const char* id);
};
struct Component* New_Component(enum COMPONENT_TYPE type ,const char* c_id); 
void Delete_Component(struct Component* component);
void Leaf_print(struct Component* pthis, int n);
void Leaf_add(struct Component* pthis, struct Component* child);
struct Component* Leaf_getComponentById(struct Component* pthis, const char* id);
void Composite_print(struct Component* pthis, int n);
void Composite_add(struct Component* pthis, struct Component* child); 
struct Component* Composite_getComponentById(struct Component* pthis, const char* id);


/* Builder Interface */
struct Builder {
    struct Component* root_;
    struct Component* curComposite_;
    struct Component* (*GetResult)(struct Builder* pthis);
};
struct Builder* New_Builder();
void Delete_Builder(struct Builder* builder);
struct Component* Builder_GetResult(struct Builder* pthis ); 
/* protected 属性のメソッドはインターフェースから外し、*/
/* メソッドの存在を隠蔽する               */
void Builder_protected_BuildLeaf (struct Builder* pthis ,const char* id);
void Builder_protected_BuildComposite (struct Builder* pthis ,const char* id); 
void Builder_protected_ChangeCurrent (struct Builder* pthis ,const char* id);
/* 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 ,const char* id) {
    struct Component* component = NULL;
    char* buf = NULL;
    component = (struct Component*)malloc(sizeof(struct Component));
    buf = (char*)malloc(sizeof(strlen(id)+1));
    strcpy(buf, id);
    component->id_ = buf;
    component->type_ = type;
    component->child_top_ = NULL;
    component->child_last_ = NULL;
    switch(type) {
    case LEAF:
        component->add = &Leaf_add;
        component->print = &Leaf_print;
        component->getComponentById = &Leaf_getComponentById;
        break;
    case COMPOSITE:
        component->add = &Composite_add;
        component->print = &Composite_print;
        component->getComponentById = &Composite_getComponentById;
        break;
    }
    return component;
}

void Delete_Component(struct Component* component) {
    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_print(struct Component* pthis ,int n) {
    indent(n);
    printf("- %s\n" ,pthis->id_);
    return;

}

struct Component* Leaf_getComponentById(struct Component* pthis ,const char* id) {
    return NULL;
}

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_print(struct Component* pthis ,int n) {
    struct Component* component = NULL;
    struct ComponentList* cur = NULL;
    indent(n);
    printf("+ %s\n" ,pthis->id_);
    cur = pthis->child_top_;
    while (cur != NULL) {
        ++n;
        component = cur->component_;
        component->print(component, n);
        --n;
        cur = cur->next_;
    }
    return;
}

struct Component* Composite_getComponentById(struct Component* pthis ,const char* id) {
    struct ComponentList* cur = NULL;
    struct Component* component = NULL;
    struct Component* target = NULL;
    if (strcmp(id, pthis->id_) == 0) {
        return pthis;
    } 
    cur = pthis->child_top_;
    while (cur != NULL) {
        component = cur->component_;
        target = component->getComponentById(component, id);
        if (target != NULL) {
            return target;
        }
        cur = cur->next_;
    }
    return NULL;
}

/* Builder Class Implementation */
struct Builder* New_Builder() {
    struct Builder* builder = NULL;
    builder = (struct Builder*)malloc(sizeof(struct Builder));
    builder->root_ = New_Component(COMPOSITE, "ROOT");
    builder->curComposite_ = builder->root_;
    builder->GetResult = &Builder_GetResult;
    return; 
}

void Delete_Builder(struct Builder* builder) {
    if (builder == NULL) {
        return;
    }
    free (builder);
    builder = NULL;
    return;
}

void Builder_protected_BuildLeaf(struct Builder* pthis ,const char* id) {
    struct Component* cur = NULL;
    struct Component* leaf = NULL;
    cur = pthis->curComposite_;
    leaf = New_Component(LEAF, id);
    cur->add(cur, leaf);
    return;
}

void Builder_protected_BuildComposite(struct Builder* pthis ,const char* id) {
    struct Component* cur = NULL;
    struct Component* composite = NULL;
    cur = pthis->curComposite_;
    composite = New_Component(COMPOSITE, id);
    cur->add(cur, composite);
    return;
}

void Builder_protected_ChangeCurrent (struct Builder* pthis ,const char* id) {
    struct Component* component = NULL;
    struct Component* target = NULL;
    component = pthis->root_;
    target = component->getComponentById(component, id);
    if (target != NULL) {
        pthis->curComposite_ = target;
    } 
    return;
}

struct Component* Builder_GetResult(struct Builder* pthis) {
    return pthis->root_;
}

/* Director */
void Director_Construct (struct Builder* builder) {
    Builder_protected_BuildLeaf(builder, "L1");
    Builder_protected_BuildLeaf(builder, "L2");
    Builder_protected_BuildComposite(builder, "A");
    Builder_protected_ChangeCurrent(builder, "A");
    Builder_protected_BuildLeaf(builder, "L3");
    Builder_protected_BuildLeaf(builder, "L4");
    return;
}

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

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

    builder = New_Builder();
    Director_Construct(builder);

    component = builder->GetResult(builder);
    component->print(component, 0);

    Delete_Component(component);
    Delete_Builder(builder);

    return 0;
}


改訂履歴

2009.2.15 C言語版を追加
     
     

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

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

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