Structural pattern
[brief description]
This pattern "compose" objects into tree structures to represent part-whole hierarchies.
[detail description]
This pattern provides a tree structures data model. Think about directories and files, directories are composite and files are leafs. Directories can have files in themselves as their children.
[expression in UML]
┌─────────┐
│ Component │
├─────────┤
├─────────┤0..*
│ + operation() │────────―─┐
│ + add() │child │
│ + remove() │ │
│ + getChild() │ │
└─────────┘ │
△ │
│ │
┌──────┴───────┐ │
│ │ │
┌────┴───┐ ┌────┴────┐ │
│ Leaf │ │ Composite │ │
├────────┤ ├─────────┤ │
├────────┤ ├─────────┤ │
│ + operation() │ │ + operation() │ 1 │
└────────┘ │ + add() │◇─┘
│ + remove() │ parent
│ + getChild() │
└─────────┘
[sample code]
(C++)
#include <stdexcept>
#include <iostream>
#include <vector>
#include <string>
enum Type
{
dic,
file
};
class Component
{
public:
Component() {}
Component(Type t_, const char* name_)
: t(t_), name(name_)
{}
virtual ~Component() {}
virtual void operation() {}
Type getType() { return t; }
const char* getName() { return name; }
virtual void add(Component* c) { throw std::runtime_error("This method is not implemented."); }
virtual void remove() { throw std::runtime_error("This method is not implemented."); }
virtual std::vectorgetChild()
{ throw std::runtime_error("This method is not implemented."); }
virtual int getSize() { throw std::runtime_error("This method is not implemented."); }
private:
Type t;
const char* name;
};
class Directory
: public Component
{
public:
Directory(const char* name)
: Component(dic, name)
{}
virtual ~Directory()
{
for (int i = 0; i < children.size(); i++) {
delete children[i];
}
}
virtual void operation()
{
std::cout << getName() << std::endl;
}
virtual void add(Component* c)
{
children.push_back(c);
}
virtual void remove()
{
Component* c = *(children.end() - 1);
delete c;
children.pop_back();
}
virtual std::vectorgetChild() { return children; }
virtual int getSize() { return children.size(); }
private:
std::vectorchildren;
int size;
};
class File
: public Component
{
public:
File(const char* name)
: Component(file, name)
{}
virtual ~File() {}
virtual void operation() { std::cout << getName() << std::endl; }
};
void printTree(Component* com, const std::string indent)
{
std::cout << indent;
if (file == com->getType()) {
com->operation();
} else if (dic == com->getType()) {
com->operation();
int size = com->getSize();
std::vectorchildren = com->getChild();
for (int i = 0; i < size; i++) {
Component* c = children[i];
printTree(c, indent + " ");
}
}
}
int main(int, char**)
{
Component* d1 = new Directory("dic 1");
Component* f1 = new File("file 1");
d1->add(f1);
Component* d2 = new Directory("dic 2");
d1->add(d2);
Component* f2 = new File("file 2");
d2->add(f2);
printTree(d1, "");
return 0;
}
No comments:
Post a Comment