No older revisions available
No older revisions available
Pluggable Selector ¶
가장 간단하게 Pluggable Behavior를 구현하는 방법은 실행될 행동을 저장해놓는 것이다. 먼저 이것의 반례, 즉 서브클래싱 한것을 보자.
~cpp class ListPane { public: Type printElement(Object& anObject) { return anObject.printString(); } }; class DollarListPane : public ListPane { public: Type printElement(Object& anObject) { return anObject.asDollarFormatString(); } }; class DiscriptionListPane : public ListPane { public: Type printElement(Object& anObject) { return anObject.desription(); } };
이런식으로 하나의 메소드만 계속 오버라이딩한다면 서브클래스들의 가치가 없을것 같다. 쉬운 해결책은 ListPane 스스로를 좀 더 유연하게 만드는 것이다. 다른 인스턴스들이 다른 메세지를 보내게 하는 것이다.
유연성 : P.S는 수신 객체에 구현되어야 한다.
확장성 : 한 오브젝트마다 최대 두번까지만 쓰자. 더 많이 쓰면 프로그램의 의도가 흐려진다. 더 많이 쓰고 싶으면 State Object를 쓰는 법이 있다.
~cpp class ListPane { private: void (ListPane::*printMessage)(); public: Type printElement(Object& anObject) { return anObject.perform(printMessage); } void initialize() { printMessage = printString; // printString은 어딘가에 구현되어 있다. } };가독성 : 그냥 서브클래싱한것보다 떨어진다.
유연성 : P.S는 수신 객체에 구현되어야 한다.
확장성 : 한 오브젝트마다 최대 두번까지만 쓰자. 더 많이 쓰면 프로그램의 의도가 흐려진다. 더 많이 쓰고 싶으면 State Object를 쓰는 법이 있다.
실행될 selector를 가지는 변수를 추가한다. 이름 뒤에 Message를 덧붙인다. selector를 실행하기 쉽게 해주는 Composed Method를 만든다.
예를 들어, 어떤 비쥬얼한 컴포넌트를 다른 것의 상대적인 부분에 위치시키고 싶다면, 상대적인 위치를 만들어주는 Pluggable Selector를 사용할 수 있다.(???)
~cpp class RelativePoint { public: static RelativePoint* centered(Figure& aFigure) { RelativePonit* rp = new RelativePoint; rp->setFigurenMessage(aFigure, center); } void setFigurenMessage(Figure& aFigure, int aSymbol()) { figure = aFigure; locationMessage = aSymbol; } };이제 일반 Point처럼 사용할 수 있다.
~cpp Point RelativePoint::asPoint() { return figure.perform(locationMessage); } Point RelativePoint::x() { return asPoint().x(); }이런 식으로 하면 CenteredRelativePoint, TopLeftRelativePoint같은 서브클래스를 만들 필요가 없다. 위에서 center라는 메세지를 추가한 것처럼, topLeft메세지를 추가만 하면 되는 것이다.