2009-08-20

Adapter pattern

一応自分の言葉で説明できるように、自分なりの解釈を書くようにしてるので、間違いがたぶんにあると思う。

[category]
Structural pattern.

[brief description]
This pattern translates one interface for a class into compatible interface.
=> Wrapper

[detail description]
Adapter class provides interfaces to client from incompatible classes or, this is my opinion, a new interface wrapped around a simple interface such as MFC. cf) MFC wraps Windows API about C++ interface, I think, I've never used MFC... --;

[expression in UML]
┌───────┐
│ Adaptee │
├───────┤
├───────┤
│+ methodB() │
└───────┘



┌───────┐ ┌───────┐
│ Client │──────>│ Adapter │
├───────┤ ├───────┤
│- adapter │ │- adaptee │
│ : Adapter │ │ : Adaptee │
├───────┤ ├───────┤
│+ doWork() │ │+ methodA() │
└───────┘ └───────┘
│ │
│ │
↓ ↓
┌─ doWork() ───┐ ┌─ methodA() ───┐
│ │ │ │
│ adapter.methodA() │ │ adaptee.methodB() │
│ │ │ │
└──────────┘ └──────────┘


[sample code]

(C++)

#include <iostream>
//---- this is adaptee classes for other file
struct Point
{
Point(int x_, int y_) : x(x_), y(y_) {}
int x;
int y;
};

std::ostream& operator<<(std::ostream& ost, Point p)
{
ost << "(" << p.x << "," << p.y << ")";
return ost;
}

class LinePrinter
{
public:
void printLine(Point* a, Point* b)
{
std::cout << "draw line from " << *a << " to " << *b << std::endl;
}

void printRectangle(Point* a, Point* b)
{
std::cout << "draw rectangle from " << *a << " to " << *b << std::endl;
}
};
//---- end adaptee classed

//---- these are adapter
class Shape
{
public:
Shape(int x1, int x2, int y1, int y2)
: p1(x1, y1), p2(x2, y2)
{}
virtual ~Shape() {}

virtual void draw() = 0;
protected:
void setPrinter(LinePrinter* printer_)
{
printer = printer_;
}
LinePrinter* printer;

Point p1;
Point p2;
};

class Line
: public Shape
{
public:
Line(int x1, int x2, int y1, int y2)
: Shape(x1, x2, y1, y2)
{
setPrinter(new LinePrinter());
}
virtual ~Line() {}

virtual void draw()
{
printer->printLine(&p1, &p2);
}
};

class Rectangle
: public Shape
{
public:
Rectangle(int x1, int x2, int y1, int y2)
: Shape(x1, x2, y1, y2)
{
setPrinter(new LinePrinter());
}
virtual ~Rectangle() {}

virtual void draw()
{
printer->printRectangle(&p1, &p2);
}
};
//---- end adapter

int main(int, char**)
{
Shape *line = new Line(0, 0, 10, 5);
Shape *rect = new Rectangle(0, 0, 10, 10); // must be square

line->draw();
rect->draw();

delete line;
delete rect;

return 0;
}

No comments:

Post a Comment