Skeleton of GOF's Design Pattern


FACADEの骸骨

FACADE


FACADE は 複数のクラスを束ね、統一したインターフェースを提供するためのパターンです。

FACADE を構成するクラス群は、通常 Facade との直接的な双方向の関連はもちません。Facade は、クラス群を利用するだけですので Facade を適用することによって、各クラスを変更することはありません。

複雑になったクラス同士の依存関係を整理し、機能を利用しやすい形にするのが Facade の役割です。


■ 『FACADEの骸骨』の構造


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

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

import java.util.*;

public class FacadeSample { 
    static public void main(String[] args) { 
        Facade facade = new Facade();

        facade.buildTree();

        System.out.println("** get File3 Component **");
        Component component = facade.getComponentById("File3");
        component.print(0);

        System.out.println("** get Folder Component **");
        component = facade.getComponentById("Folder");
        component.print(0);

        System.out.println("** list Leaf Component **");
        ListIterator it = facade.getComponentsByType("Leaf");
        while (it.hasNext()) {
           component = (Component)it.next();
           component.print(0);
        }

        System.out.println("** list Composite Component **");
        it = facade.getComponentsByType("Composite");
        while (it.hasNext()) {
           component = (Component)it.next();
           System.out.println("<" + component.getName() + "'s Structure>");
           component.print(0);
        }

    } 
}

class Facade { 
    Component _component = null;
    LinkedList _compositeList = new LinkedList();
    LinkedList _leafList = new LinkedList();
    HashMap _componentMap = new HashMap();

    public void buildTree() {
        Composite root = new Composite("Root");
        Leaf file1 = new Leaf("File1");
        Leaf file2 = new Leaf("File2");
        root.add(file1);
        root.add(file2);

        _compositeList.add(root);
        _leafList.add(file1);
        _leafList.add(file2);
        _componentMap.put(root.getName(), root);
        _componentMap.put(file1.getName(), file1);
        _componentMap.put(file2.getName(), file2);

        Composite folder = new Composite("Folder");
        Leaf file3 = new Leaf("File3");
        Leaf file4 = new Leaf("File4");
        folder.add(file3);
        folder.add(file4);

        _compositeList.add(folder);
        _leafList.add(file3);
        _leafList.add(file4);
        _componentMap.put(folder.getName(), folder);
        _componentMap.put(file3.getName(), file3);
        _componentMap.put(file4.getName(), file4);

        _component = root;
    }
    public ListIterator getComponentsByType(String type) {
        if (_component == null) return null;
        if (type.equals("Composite")) {
            return _compositeList.listIterator();
        } else if (type.equals("Leaf")) {
            return _leafList.listIterator();
        }
        return null;
    }
    public Component getComponentById(String name) {
        return (Component)_componentMap.get(name);
    }
}

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

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

class Composite extends Component {
    private LinkedList _children = new LinkedList();
    public Composite(String name) {
        super(name);
    }
    public void add(Component component) {
        _children.add(component);
    }
    public void print(int n) {
        indent(n);
        System.out.println("+ " + getName());
        ListIterator it = _children.listIterator();
        while (it.hasNext()) {
            Component component = (Component)it.next();
            ++n;
            component.print(n);
            --n;
        }
    }
}

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

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

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

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

class Composite : public Component {
public:
    Composite(const string& name);
    ~Composite();
    void add(Component* component);
    virtual void print(int n) const;
private:
    list<Component*> children_;
};

class Facade { 
public:
    Facade();
    ~Facade();
    void buildTree();
    const list<Component*> getComponentsByType(const string& type) const;
    Component* getComponentById(const string& id) const;
private:
    list<Component*> compositeList_;
    list<Component*> leafList_;
    map<string, Component*> componentMap_;
    Component* component_;
};


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

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

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

Facade::Facade() { }
Facade::~Facade() { 
    delete component_;
}
void Facade::buildTree() {
    Composite* root = new Composite("Root");
    Leaf* file1 = new Leaf("File1");
    Leaf* file2 = new Leaf("File2");
    root->add(file1);
    root->add(file2);

    compositeList_.push_back(root);
    leafList_.push_back(file1);
    leafList_.push_back(file2);
    componentMap_[root->getName()] = root;
    componentMap_[file1->getName()] = file1;
    componentMap_[file2->getName()] = file2;

    Composite* folder = new Composite("Folder");
    Leaf* file3 = new Leaf("File3");
    Leaf* file4 = new Leaf("File4");
    folder->add(file3);
    folder->add(file4);

    compositeList_.push_back(folder);
    leafList_.push_back(file3);
    leafList_.push_back(file4);
    componentMap_[folder->getName()] = folder;
    componentMap_[file3->getName()] = file3;
    componentMap_[file4->getName()] = file4;
    
    root->add(folder);
    component_ = root;
}

const list<Component*> Facade::getComponentsByType(const string& type) const {
    if (type == "Composite") {
        return compositeList_;
    } else if (type == "Leaf") {
        return leafList_;
    }
}
Component* Facade::getComponentById(const string& name) const {
    map<string, Component*>::const_iterator it = componentMap_.find(name);
    return (*it).second;
}


int main() {
    Facade* facade = new Facade();

    facade->buildTree();

    cout << "** get File3 Component **" << endl;
    Component* component = facade->getComponentById("File3");
    component->print(0);

    cout << "** get Folder Component **" << endl;
    component = facade->getComponentById("Folder");
    component->print(0);

    cout << "** list Leaf Component **" << endl;
    list<Component*> components = facade->getComponentsByType("Leaf");
    list<Component*>::const_iterator it = components.begin();
    while (it != components.end()) {
       (*it)->print(0);
       ++it;
    }

    cout << "** list Composite Component **" << endl;
    components = facade->getComponentsByType("Composite");
    it = components.begin();
    while (it != components.end()) {
       (*it)->print(0);
       ++it;
    }
} 

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

struct Component;

/* 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 {
    enum COMPONENT_TYPE type_;
    char* data_;
    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 ,char* data);
void Delete_Component(struct Component* comp);
void Leaf_add(struct Component* pthis ,struct Component* child);
void Leaf_Operation(struct Component* pthis ,int n);
void Composite_add(struct Component* pthis ,struct Component* child);
void Composite_Operation(struct Component* pthis ,int n);

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

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

/* Component Class Implementation */
struct Component* New_Component(enum COMPONENT_TYPE type ,char* data) {
    struct Component* component = NULL;
    char* buf = NULL;

    component = (struct Component*)malloc(sizeof(struct Component));
    buf = (char*)malloc(strlen(data)+1);
    strcpy(buf ,data);

    component->type_ = type;
    component->data_ = buf;
    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;
    }

    free(component->data_);
    component->data_ = NULL;
    if (component->type_ == COMPOSITE) {
        cur = component->child_top_;
        while (cur != NULL) {
            tmp = cur->next_;
            Delete_Component(cur->component_);
            cur = tmp;
        }
    }

    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:%s\n" ,pthis->data_);
    return;
}

void Composite_add(struct Component* pthis ,struct Component* child) {
    struct Component* cur = NULL;
    struct ComponentList* list = NULL;
    list = New_ComponentList(child);
    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:%s\n" ,pthis->data_);
    cur = pthis->child_top_;
    while (cur != NULL) {
        ++n;
        component = cur->component_;
        component->Operation(component, n);
        --n;
        cur = cur->next_;
    }
    return;
}

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

/* Facade Implementation */
struct Component* gComponentRoot = NULL;
struct ComponentList* gCompositeListTop  = NULL;
struct ComponentList* gCompositeListLast = NULL;
struct ComponentList* gLeafListTop  = NULL;
struct ComponentList* gLeafListLast = NULL;

void Facade_private_CompositeList_add(struct Component* component) {
    struct ComponentList* list = New_ComponentList(component);
    if (gCompositeListTop == NULL) {
        gCompositeListTop  = list;
        gCompositeListLast = list;
    } else {
        gCompositeListLast->next_ = list;
        gCompositeListLast = list;
    }
    return;
}

void Facade_private_LeafList_add(struct Component* leaf) {
    struct ComponentList* list = New_ComponentList(leaf);
    if (gLeafListTop == NULL) {
        gLeafListTop  = list;
        gLeafListLast = list;
    } else {
        gLeafListLast->next_ = list;
        gLeafListLast = list;
    }
    return;
}

struct ComponentList* Facade_private_CopyComponentList(struct ComponentList* list) {
    struct ComponentList* copy = NULL;
    struct ComponentList* top = NULL;

    top = New_ComponentList(list->component_);
    top->next_ = list->next_;
    list = list->next_;
    while (list != NULL) {
        copy = New_ComponentList(list->component_);
        copy->next_ = list->next_;
        list = list->next_;
    }
    return top;
}

void Facade_BuildTree() {
    struct Component* composit1 = NULL;
    struct Component* leaf1_1 = NULL;
    struct Component* leaf1_2 = NULL;
    struct Component* composit2 = NULL;
    struct Component* leaf2_1 = NULL;
    struct Component* leaf2_2 = NULL;

    composit1 = New_Component(COMPOSITE ,"Root");
    Facade_private_CompositeList_add(composit1);
    leaf1_1 = New_Component(LEAF ,"File1");
    Facade_private_LeafList_add(leaf1_1);
    leaf1_2 = New_Component(LEAF ,"File2");
    Facade_private_LeafList_add(leaf1_2);

    composit1->add(composit1 ,leaf1_1);
    composit1->add(composit1 ,leaf1_2);

    composit2 = New_Component(COMPOSITE ,"Folder");
    Facade_private_CompositeList_add(composit2);
    leaf2_1 = New_Component(LEAF ,"File3");
    Facade_private_LeafList_add(leaf2_1);
    leaf2_2 = New_Component(LEAF ,"File4");
    Facade_private_LeafList_add(leaf2_2);

    composit2->add(composit2 ,leaf2_1);
    composit2->add(composit2 ,leaf2_2);

    composit1->add(composit1 ,composit2);

    gComponentRoot = composit1;
    return;
}

struct ComponentList* Facade_GetComponentById(const char* id) {
    struct ComponentList* list = NULL;
    struct ComponentList* new_top  = NULL;
    struct ComponentList* new_last = NULL;

    list = gCompositeListTop;
    while (list != NULL) {
        if (strstr(list->component_->data_, id) != NULL) {
            break;
        }
        list = list->next_;
    }
    if (list != NULL) {
        if (new_top == NULL) {
            new_top = New_ComponentList(list->component_);
            new_last = new_top;
        } else {
            new_last->next_ = New_ComponentList(list->component_);
            new_last = new_last->next_;
        }
    }

    list = gLeafListTop;
    while (list != NULL) {
        if (strstr (list->component_->data_, id) != NULL) {
            break;
        }
        list = list->next_;
    }
    if (list != NULL) {
        if (new_top == NULL) {
            new_top = New_ComponentList(list->component_);
            new_last = new_top;
        } else {
            new_last->next_ = New_ComponentList(list->component_);
            new_last = new_last->next_;
        }
    }

    return new_top;
}

struct ComponentList* Facade_GetComponentByType(enum COMPONENT_TYPE type) {
    struct ComponentList* list = NULL;
    if (type == COMPOSITE) {
        return Facade_private_CopyComponentList(gCompositeListTop);
    } else if (type == LEAF) {
        return Facade_private_CopyComponentList(gLeafListTop);
    }
    return NULL;
}

void Facade_DeleteTree() {
    Delete_ComponentList(gCompositeListTop);
    Delete_ComponentList(gLeafListTop);
    Delete_Component(gComponentRoot);
    return;
}

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

    Facade_BuildTree();

    printf("** get File3 Component **\n");
    list = Facade_GetComponentById("File3");
    component = list->component_;
    component->Operation(component ,0);
    Delete_ComponentList(list);

    printf("** get Folder Component **\n");
    list = Facade_GetComponentById("Folder");
    component = list->component_;
    component->Operation(component ,0);
    Delete_ComponentList(list);

    printf("** list Leaf Component **\n");
    list = Facade_GetComponentByType(LEAF);
    while (list != NULL) {
        component = list->component_;
        component->Operation(component ,0);
        list = list->next_;
    }
    Delete_ComponentList(list);

    printf("** list Composite Component **\n");
    list = Facade_GetComponentByType(COMPOSITE);
    while (list != NULL) {
        component = list->component_;
        component->Operation(component ,0);
        list = list->next_;
    }
    Delete_ComponentList(list);

    Facade_DeleteTree();

    return 0;
}


改訂履歴

2009.2.22 C言語版を追加
     
     

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

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

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