이것은 더 많은 디자인 질문입니다 ...장식하려는 클래스에서 상속받을 수없는 경우 Decorator 패턴을 어떻게 구현합니까?
1) 개체가 "봉인 된"것으로 표시되어 확장 할 수 없다는 의미입니다. 2) 또는 메소드를 오버라이드하고 싶지만 가상은 아닙니다.
그럼 어떻게 할 수 있습니까? 소스 코드 (예 : 타사 라이브러리)가 없으면 클래스 소스 코드를 변경할 수 없습니다.
이것은 더 많은 디자인 질문입니다 ...장식하려는 클래스에서 상속받을 수없는 경우 Decorator 패턴을 어떻게 구현합니까?
1) 개체가 "봉인 된"것으로 표시되어 확장 할 수 없다는 의미입니다. 2) 또는 메소드를 오버라이드하고 싶지만 가상은 아닙니다.
그럼 어떻게 할 수 있습니까? 소스 코드 (예 : 타사 라이브러리)가 없으면 클래스 소스 코드를 변경할 수 없습니다.
타사 클래스를 래핑하고 해당 클래스를 장식하는 고유 한 클래스를 만들 수 있습니다. 클래스는 래핑 된 클래스 구현을 사용합니다. 랩퍼 클래스는 어댑터의 역할을합니다.
1) 타사 코드에 봉인 클래스의 인스턴스를 전달하는 : 당신이 정말이 코드를 통해 얼마나 많은 컨트롤에 따라 취할 수있는 방법의
많은? 그렇다면 제 3자가 구체적인 객체 대신 인터페이스를 허용하도록기도하는 것 외에는 할 수있는 일이별로 없습니다.
봉인 된 클래스의 메서드를 가로 채기 위해 CLR에 후크를 작성하는 것이 가능합니다. 일부 비웃음 프레임 워크가 가상 메서드가 아닌 클래스와 봉인 된 클래스를 조롱하는 방식입니다. I 은 타사 코드가 특정 개체 구현에 대해 작성되었으며 타사 코드의 코드에서 구현을 스왑 아웃하는 것이 중요하지 않은 결과를 초래할 수 있으므로이 방법을 권장합니다.
2) 자신의 코드로 봉인 된 클래스를 사용하고 있습니까? 그렇다면 가제트 래퍼로 이동하십시오! 봉인 된 클래스와 동일한 공용 메서드를 사용하여 봉인되지 않은 클래스를 만들고 공용 메서드를 봉인 된 개체로 전달한 다음 필요에 따라 클래스의 기능을 재정의 할 수 있습니다.
3) 봉인 된 클래스에 대한 코드를 소유하고 있습니까? 그렇다면 클래스 정의를 찾고 'sealed'키워드를 두 번 클릭하여 강조 표시하고 필요에 따라 삭제 키를 누르십시오.) 대신 공개 된 메소드가있는 인터페이스에 대해 봉인 된 객체를 허용하는 메소드를 교체하십시오.
Decorator 패턴에는 상속이 필요하지 않습니다. 가장 간단한 경우는 장식하려는 객체가 인터페이스를 구현하는 경우입니다. 당신은 그냥 할 수있는 지금
[ IWindow ]
[ + Draw() ]
---------------
|
+--- [ Window ]
| [ + Draw() ]
|
|
+--- [ DecoratedWindow ]
[ + Draw() ]
-------------------
|
+--- [ BorderDecorator ]
|
+--- [ VerticalScrollbarDecorator ]
|
+--- [ HorizontalScrollbarDecorator ]
: 가능한 무엇인지
IWindow w = new BorderDecorator(
new HorizontalScrollBarDecorator(
new VerticalScrollBarDecorator(
new Window(80, 24))));
// This is a window with a border and scrollbars, even though
// the original Window class has no idea what those are.
w.Draw();
구체적인 당신이하려는 클래스의 정확한 특성에 따라 달라집니다 그리고 당신의 장식은 단순히 동일한 인터페이스를 구현할 수 있습니다 장식하다.
+1 인터페이스를 디자인 할 때. 클래스가 상속받을 수 없다면 이것은 특히 중요합니다! – Aaronaught
상속받을 수없고 원래 클래스가 데코레이터에 구현할 수있는 인터페이스를 구현하지 않으면 프록시 클래스 또는 어댑터를 사용해보아야한다고 생각합니다. 그리고 이것이 가능하지 않다면 항상 "대체 기술 리소스"가 있습니다. conversion operator을 정의하여 장식자를 원래의 것 (이 옵션은 좋지 않다고 생각하지만)으로 캐스팅 할 수 있습니다.
그러나 유형이 다르므로 주제 클래스를 프록시 클래스로 대체 할 수 없습니다. – Ikke
@ikke : 그건 사실이야. 따라서 나는 프록시 패턴을 말하지 않았다. – Ikaso
은 프록시가 아닌 어댑터일까요? –