U E D R , A S I H C RSS

Gof/Adapter


1. Adapter

1.1. Intent

클래슀의 μΈν„°νŽ˜μ΄μŠ€λΌ λ‹€λ₯Έ ν•„μš”ν•œ 클래슀의 μΈν„°νŽ˜μ΄μŠ€μ— 맞게 λ³€ν™˜ν•΄μ€λ‹€. Adapter λŠ” μ„œλ‘œ ν˜Έν™˜μ„±μ΄ μ—†λŠ” μΈν„°νŽ˜μ΄μŠ€λ“€λΌλ¦¬λΌλ„ 같이 μž‘λ™ν•  수 μžˆκ²Œλ” ν•΄μ€λ‹€.

1.2. Also Known As

Wrapper (였히렀 이 단어가 더 μΉœμˆ™ν•  것이닀.)

1.4. Applicability

λ‹€μŒκ³Ό 같은 κ²½μš°μ— AdapterPatternλΌ μ΄μš©ν•œλ‹€.
  • μ΄λΈ λ§Œλ“€μ–΄μ Έ μžˆλŠ” ν΄λž˜μŠ€λΌ μ‚¬μš©ν•˜κ³  μ‹Άμ§€λ§Œ, μΈν„°νŽ˜μ΄μŠ€κ°€ μ›ν•˜λŠ” 방식과 μΌμΉ˜ν•˜μ§€ μ•Šμ„λ•Œ.
  • 관련성이 μ—†κ±°λ‚˜, μ˜ˆμΈ‘ν•˜μ§€ λͺ»ν•œ ν΄λž˜μŠ€λ“€κ³Ό ν˜‘λ™ν•˜λŠ” μž¬μ‚¬μš©κ°€λŠ₯ν•œ ν΄λž˜μŠ€λΌ μƒμ„±ν•˜κΈ° μ›ν• λ•Œ. 이 경우 ν΄λž˜μŠ€λ“€μ΄ ν˜Έν™˜μ„±μ„ κ°€μ§€λŠ” μΈν„°νŽ˜μ΄μŠ€λΌ ν•„μš”λ‘œ ν•˜μ§€ μ•ŠλŠ”λ‹€.
  • (object adapter 의 κ²½μš°μ—λ§Œ ν•΄λ‹Ή) ν˜„μž¬ μ΄λΈ λ§Œλ“€μ–΄μ§„ μ—¬λŸ¬κ°œμ˜ subclassκ°€ ν•„μš”ν•œ 경우, ν•˜μ§€λ§Œ 각각의 μ„œλΈŒν΄λž˜μŠ€λ“€μ— λŒ€ν•œ μΈν„°νŽ˜μ΄μŠ€λΌ ν•˜λŠ” 것은 λΉ„νš¨μœ¨μ μ΄λ‹€. 이 경우 parent class의 μΈν„°νŽ˜μ΄μŠ€λΌ adapt ν•  수 μžˆλ‹€.

1.5. Structure

adapter ν΄λž˜μŠ€λŠ” ν•˜λ‚˜μ˜ interfaceλΌ λ‹€λ₯Έ interface 에 μ ν•©ν•˜κ²Œ 맞좰주기 μœ„ν•΄ (말 κ·ΈλŒ€λ‘œ μ–΄λŽν„° μ—­ν• ~) 닀쀑상속을 μ΄μš©ν•œλ‹€.


adapter κ°μ²΄λŠ” object composition 에 μ˜μ‘΄ν•œλ‹€.

1.6. Participants

  • Target (Shape)
    - ν΄λΌμ΄μ–ΈνŠΈκ°€ μ΄μš©ν•œ domain-specificν•œ μΈν„°νŽ˜μ΄μŠ€λΌ μ •μ˜ν•œλ‹€.
  • Client (DrawingEditor)
    - Target의 μΈν„°νŽ˜μ΄μŠ€μ— 따라 객체듀과 μƒν˜Έμž‘μš©μ„ ν•œλ‹€.
  • Adaptee (TextView)
    - adapting이 ν•„μš”ν•œ ν˜„μ‘΄ν•˜λŠ” interfaceλΌ μ •μ˜ν•œλ‹€.
  • Adapter (TextShape)
    - Adpatee 의 μΈν„°νŽ˜μ΄μŠ€λΌ Target 의 μΈν„°νŽ˜μ΄μŠ€μ— adapt μ‹œν‚¨λ‹€.

1.7. Collaborations

  • ν•΄λ‹Ή ν΄λž˜μŠ€λΌ μ΄μš©ν•˜λŠ” Client듀은 Adapter μΈμŠ€ν„΄μŠ€μ˜ operation듀을 ν˜ΈμΆœν•œλ‹€. adapterλŠ” ν•΄λ‹Ή Client의 μš”μ²­μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•΄ Adaptee 의 operation을 ν˜ΈμΆœν•œλ‹€.

1.9. Implementation



~cpp 
directoryDisplay :=
	(TreeDisplay on: treeRoot)
		getChildrenBlock:
			[:node | node getSubdirectories]
		createGraphicNodeBlock:
			[:node | node createGraphicNode].

1.10. Sample Code

We'll give a brief sketch of the implementation of class and object adapters for the Motivation example beginning with the classes Shape and TextView.
~cpp 
class Shape {
public:
	Shape ();
	virtual void BoundingBox(Point& bottomLeft, Point& topRight) const;
	virtual Manipulator* CreateManipulator () const;
};

class TextView {
public:
	TextView ();
	void GetOrigin (Coord& x, Coord& y) const;
	void GetExtent (Coord& width, Coord& height) const;
	virtual bool IsEmpty () const;

Shape assumes a bounding box defined by its opposing corners. In contrast, TextView is defined by an origin, height, and width. Shape also defines a CreateManipulator operation for creating a Manipulator object, which knowns how to animate a shape when the user manipulates it. TextView has no equivalent operation. The class TextShape is an adapter between these different interfaces.

A class adapter uses multiple inheritance to adapt interfaces. The key to class dapters is to use one inheritance branch to inherit the interface and another branch to inherit the implementation. The usual way to make this distinction in C++ is to inherit the interface publicly and inherit the implementation privately. We'll use this convention to define the TextShape adapter.
~cpp 
class TextShape : public Shape, private TextView {
public:
	TextShape ();

	virtual void BoundingBox (Point& bottomLeft, Point& topRight) const;
	virtual bool IsEmpty () const;
	virtual Manipulator* CreateManipulator () const;
};

The BoundingBox operation converts TextView's interface to conform to Shape's.
~cpp 
void TextShape::boundingBox (Point& bottomLeft, Point& topRight) const {
	Coord bottom, left, width, height;

	GetOrigin (bottom, left);
	GetExtent (width, height);

	bottomLeft = Point (bottom, left);
	topRight = Point (bottom + height, left + width);

The IsEmpty operations demonstrates the direct forwarding of requests common in adapter implementations:
~cpp 
bool TextShape::ImEmpty () const {
	return TextView::IsEmpty ();
}

Finally, we define CreateManipulator (which isn't supported by TextView) from scratch. Assume we've already implemented a TextManipulator class that supports manipulation of a TextShape.
~cpp 
Manipulator* TextShape::CreateManipulator () const {
	return new TextManipulator (this);

The object adapter uses object composition to combine classes with different interfaces. In this approach, the adapter TextShape maintains a pointer to TextView.
~cpp 
class TextShape : public Shape {
public:
	TextShape (TextView*);

	virtual void BoundingBox (Point& bottomLeft, Point& topRight) const;

	virtual bool IsEmpty () const;
	virtual Manipulator* CreateManipulator () const;
private:
	TextView* _text;
};

TextShape must initialize the pointer to the TextView instance, and it does so in the constructor. It must also call operations on its TextView object whenever its own operations are called. In this example, assume that the client creates the TextView object and passes it to the TextShape constructor.
~cpp 
TextShape::TextShape (TextView* t) {
	_text = t;
}

void TextShape::BoundingBox (
	Point& bottomLeft, Point& topRight
) const {
	Coord bottom, left, width, height;

	_text->GetOrigin (bottom, left);
	_text->GetExtent (width, height);

	bottomLeft = Point (bottom, left);
	topRight = Point (bottom + height, left + width);
}

bool TextShape::IsEmpty () const {
	return _text->IsEmpty ();
}

CreateManipulator's implementation doesn't change from the class adapter version, since it's implemented from scratch and doesn't reuse any existing TextView functionality.

~cpp 
Manipulator* TextShape::CreateManipulator () const {
	return new TextManipulator (this);
}

Compare this code the class adapter case. The object adapter requires a little more effort to write, but it's more flexible. For example, the object adapter version of TextShape will work equally well with subclasses of TextView -- the client simply passes an instance of a TextView subclass to the TextShape constructor.

1.12. Related Patterns

BridgePattern 은 adapter object와 λΉ„μŠ·ν•œ κ΅¬μ‘°λΌ κ°€μ§„λ‹€. ν•˜μ§€λ§Œ BridgePattern의 AdapterPatternκ³Ό κ·Έ μ˜λ„κ°€ λ‹€λ₯΄λ‹€. BridgePattern은 μ‹€μ œ κ΅¬ν˜„λΆ€μ™€ interface뢀뢄을 λΆ„λ¦¬μ‹œμΌœ μ‹€μ œ κ΅¬ν˜„ 뢀뢄이 λ‹€μ–‘ν•˜κ³  독립적일 수 μžˆλ„λ‘ ν•˜κΈ° μœ„ν•œ 것이닀. adapterλŠ” ν˜„μž¬ μ΄λΈ μ‘΄μž¬ν•˜λŠ” 객체에 λŒ€ν•œ interfaceλΌ λ°”κΎΈκΈ° μœ„ν•΄ μ΄μš©λœλ‹€.

DecoratorPattern은 객체에 λŒ€ν•œ μΈν„°νŽ˜μ΄μŠ€μ˜ 변화없이 κ°μ²΄λΌ ν™•μž₯μ‹œν‚¨λ‹€. Decorator λŠ” adapter보닀 더 application에 λŒ€ν•΄ 투λͺ…적이닀. 결둠적으둜 DecoratorPattern은 μž¬κ·€μ μΈ composition을 μ œκ³΅ν•œλ‹€. 이것은 μˆœμˆ˜ν•œ adapterλ‘œμ„œλŠ” λΆˆκ°€λŠ₯ν•˜λ‹€.

ProxyPattern은 ν•΄λ‹Ή 객체에 λŒ€ν•œ λŒ€λ¦¬μž 역할을 ν•˜λ©°, μ‹€μ œ 객체에 λŒ€ν•œ interfaceλΌ λ³€ν™”μ‹œν‚€μ§€ μ•ŠλŠ”λ‹€.


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:18
Processing time 0.0290 sec