프록시, 데코레이터, 어댑터 및 브리지 패턴은 어떻게 다릅니 까?


403

프록시 패턴을보고 있었고 데코레이터, 어댑터 및 브리지 패턴과 같은 끔찍한 것 같습니다. 내가 뭔가를 오해하고 있습니까? 차이점이 뭐야? 프록시 패턴을 사용하는 이유는 무엇입니까? 실제 프로젝트에서 과거에 어떻게 사용 했습니까?


4
매우 유사 해 보이지만 의도가 다른 패턴이 종종 있습니다 (전략 및 상태 패턴이 떠오름). 디자인 패턴이 일반적인 견고한 디자인 원칙을 기반으로한다는 사실에 기인한다고 생각합니다.
Jason Down

5
이 네 가지 패턴은 구현 세부 사항이 동일합니다. State verses 전략은 적어도 stateless full states로 구성 될 수 있습니다 (대부분). 종종 전략은 메서드 주입 일뿐입니다. 여기서 상태 패턴은 인터페이스를 사용하여 메서드 호출보다 더 많은 것을 추상화합니다. 또한이 전략은 OO 세계에서 기능적 프로그래밍을 가능하게하는 해킹입니다.
Charles Graham

답변:


648

프록시, 데코레이터, 어댑터 및 브리지는 모두 클래스 "래핑"의 변형입니다. 그러나 그들의 용도는 다릅니다.

  • 프록시 는 개체를 지연 인스턴스화하거나 원격 서비스를 호출한다는 사실을 숨기거나 개체에 대한 액세스를 제어하려는 경우에 사용할 수 있습니다.

  • 데코레이터 는 "스마트 프록시"라고도합니다. 이것은 객체에 기능을 추가하려고 할 때 사용되지만 해당 객체의 유형을 확장하지는 않습니다. 이를 통해 런타임에 그렇게 할 수 있습니다.

  • 어댑터 는 추상 인터페이스가 있고 해당 인터페이스를 기능적인 역할은 비슷하지만 다른 인터페이스를 가진 다른 객체에 매핑하려고 할 때 사용됩니다.

  • Bridge 는 Adapter와 매우 유사하지만 추상 인터페이스와 기본 구현을 모두 정의 할 때 Bridge라고합니다. 즉, 일부 레거시 또는 타사 코드에 적응하지 않고 모든 코드의 설계자이지만 다른 구현을 바꿀 수 있어야합니다.

  • Facade 는 하나 이상의 클래스 서브 시스템에 대한 상위 레벨 (읽기 : 단순) 인터페이스입니다. 표현하기 위해 여러 객체가 필요한 복잡한 개념이 있다고 가정합니다. 호출해야하는 메소드가있는 오브젝트를 항상 알 수 없기 때문에 해당 오브젝트 세트를 변경하는 것은 혼란 스럽습니다. 이제 객체 컬렉션에 대해 수행 할 수있는 모든 복잡한 작업에 대해 높은 수준의 방법을 제공하는 Facade를 작성해야합니다. 예 : 같은 방법으로 학교 섹션에 대한 도메인 모델, countStudents(), reportAttendance(), assignSubstituteTeacher(), 등.


7
좋은 대답입니다. 야생에서 볼 수있는 몇 가지 예를 추가 할 가치가 있습니까? 예를 들어 웹 서비스의 프록시 클래스. 나에게서 +1
Rob Cooper

5
@Rob : 감사합니다.하지만이 답변은 짧고 달콤합니다. 나는 야생에서 예를 들어 다른 답을 쓰도록 권합니다!
Bill Karwin

8
@RobertDailey Decorator는 제어 유형 계층 구조를 피하는 것이 좋습니다. 예를 들어 , GUI에 창이 있고 선택적인 스크롤 막대를 원한다고 가정하십시오. Window, VScrollWindow, HScrollWindow 및 VHScrollWindow 클래스가 있거나 Window에서 VScroll 및 HScroll 데코레이터를 만들 수 있습니다.
Eva

1
@RobertDailey, Decorator 작곡입니다.
Bill Karwin

1
래핑 된 객체의 인터페이스를 1 : 1로 복제 한 다음 몇 가지 방법을 추가하려면 어떻게해야합니까? 이것은 데코레이터 또는 어댑터입니까?
donquixote

198

Bill의 답변에서 알 수 있듯이 사용 사례는 다릅니다 .

그들의 구조도 마찬가지입니다.

  • 프록시데코레이터는 모두 래핑 된 유형과 동일한 인터페이스를 갖지만 프록시는 인스턴스를 생성하는 반면 데코레이터는 생성자에서 인스턴스를 생성합니다.

  • AdapterFacade는 모두 랩과 인터페이스가 다릅니다. 그러나 어댑터는 기존 인터페이스에서 파생되지만 파사드는 새 인터페이스를 만듭니다.

  • 브리지어댑터는 모두 기존 유형을 가리 킵니다. 그러나 브릿지는 추상 유형을 가리키고 어댑터는 콘크리트 유형을 가리킬 수 있습니다. 브리지를 사용하면 런타임에 구현을 쌍으로 연결할 수 있지만 어댑터는 일반적으로 그렇지 않습니다.


30
Bill의 답변과 함께 5 가지 디자인 패턴 장을 마무리했습니다. 그것들을 책에 대한 더 높은 수준의 (읽기 : 더 간단한) 인터페이스라고 부를 수 있습니다.
Jonas Eicher

54

주제에 대한 나의 견해.

네 가지 패턴 모두 공통점이 많으며, 네 가지 패턴 모두 비공식적으로 래퍼 또는 래퍼 패턴이라고도합니다. 모든 구성을 사용하고 주제를 래핑하고 어느 시점에서 주제에 실행을 위임하면 한 메소드 호출을 다른 메소드 호출에 맵핑합니다. 그들은 고객에게 다른 객체를 구성하고 모든 관련 데이터를 복사해야 할 필요성을 아끼지 않습니다. 현명하게 사용하면 메모리와 프로세서가 절약됩니다.

느슨한 결합을 촉진함으로써 안정적인 코드가 불가피한 변경에 덜 노출되고 동료 개발자가 더 잘 읽을 수있게됩니다.

어댑터

어댑터는 주제 (어댑터)를 다른 인터페이스에 적응시킵니다. 이런 식으로 명목상 다른 유형의 컬렉션에 객체를 추가 할 수 있습니다.

어댑터는 관련 메소드 만 클라이언트에 노출하고 다른 모든 메소드를 제한하여 외부 라이브러리 적응과 같은 특정 컨텍스트에 대한 사용 의도를 공개하여 애플리케이션 요구에 덜 일반적이며 집중적으로 보이도록합니다. 어댑터는 코드의 가독성과 자기 설명을 향상시킵니다.

어댑터는 한 팀을 다른 팀의 휘발성 코드로부터 보호합니다. 해외 팀을 다룰 때 구세주 도구 ;-)

덜 언급 된 목적은 주제 클래스가 주석을 초과하지 않도록하는 것입니다. 주석을 기반으로하는 많은 프레임 워크에서 이것은 그 어느 때보 다 중요한 사용법이되었습니다.

어댑터는 단일 상속에 대한 Java 제한 사항을 극복하는 데 도움이됩니다. 하나의 엔벨로프에 여러 명의 적응자를 결합하여 여러 상속을 감수 할 수 있습니다.

코드 측면에서 어댑터는 "얇다". 단순히 적응자 메소드를 호출하고 그러한 호출을하기 위해 필요한 데이터 변환을하는 것 외에, 적응자 클래스에 많은 코드를 추가해서는 안됩니다.

JDK 또는 기본 라이브러리에는 좋은 어댑터 예제가 없습니다. 응용 프로그램 개발자는 라이브러리를 응용 프로그램 특정 인터페이스에 맞추기 위해 어댑터를 작성합니다.

데코레이터

데코레이터는 하나의 메소드를 다른 메소드에 맵핑 할뿐만 아니라 더 많은 것을 수행하고 일부 주제 메소드의 동작을 수정하며 주제 메소드를 전혀 호출하지 않고 다른 오브젝트, 헬퍼 오브젝트에 위임하지 않기로 결정할 수 있습니다.

데코레이터는 일반적으로 주제에 대한 로깅, 암호화, 형식 지정 또는 압축과 같은 래핑 된 객체에 (투명하게) 기능을 추가합니다. 이 새로운 기능은 많은 새로운 코드를 가져올 수 있습니다. 따라서 데코레이터는 일반적으로 어댑터보다 훨씬 "더 빠르다".

데코레이터는 주제 인터페이스의 하위 클래스 여야합니다. 피사체 대신 투명하게 사용할 수 있습니다. BufferedOutputStream을 참조하십시오. 여전히 OutputStream이며 그대로 사용할 수 있습니다. 이는 어댑터와의 주요 기술적 차이점입니다.

전체 데코레이터 제품군의 교재 예제는 JDK (Java IO)에 있습니다. BufferedOutputStream , FilterOutputStreamObjectOutputStream 과 같은 모든 클래스 는 OutputStream의 데코레이터입니다 . 그들은 하나의 데코레이터가 다시 장식되어 더 많은 기능을 추가하는 양파 층이 될 수 있습니다.

대리

프록시는 일반적인 래퍼가 아닙니다. 프록시 주제 인 랩핑 된 오브젝트는 프록시 작성시 아직 존재하지 않을 수 있습니다. 프록시는 종종 내부적으로 만듭니다. 요청시 생성 된 무거운 객체이거나 다른 JVM 또는 다른 네트워크 노드의 원격 객체 일 수도 있고 원시 코드의 구성 요소 인 Java 이외의 객체 일 수도 있습니다. 랩핑하거나 다른 오브젝트에 위임 할 필요가 없습니다.

가장 일반적인 예는 원격 프록시, 무거운 객체 이니셜 라이저 및 액세스 프록시입니다.

  • 원격 프록시 – 주제는 원격 서버, 다른 JVM 또는 Java 이외의 시스템에 있습니다. 프록시는 메소드 호출을 RMI / REST / SOAP 호출 또는 필요한 모든 것으로 변환하여 클라이언트를 기본 기술에 노출시키지 않도록 보호합니다.

  • 지연로드 프록시 – 첫 번째 사용 또는 첫 번째 집중 사용으로 만 오브젝트를 완전히 초기화하십시오.

  • 액세스 프록시 – 주제에 대한 액세스를 제어합니다.

정면

Facade는 Least Knowledge (Law of Demeter)의 디자인 원칙과 밀접한 관련이 있습니다. 외관은 어댑터와 매우 유사합니다. 둘 다 감싸고 둘 다 한 객체를 다른 객체에 매핑하지만 의도가 다릅니다. Facade는 피사체의 복잡한 구조, 복잡한 객체 그래프를 평탄화하여 복잡한 구조에 대한 액세스를 단순화합니다.

Facade는 복잡한 구조를 감싸서 평평한 인터페이스를 제공합니다. 이것은 대상 구조에서 클라이언트 객체가 내부 관계에 노출되는 것을 방지하여 느슨한 결합을 촉진합니다.

다리

구현뿐만 아니라 추상화가 다양한 어댑터 패턴의 더 복잡한 변형. 위임에 하나 이상의 간접 참조를 추가합니다. 추가 위임은 다리입니다. 적응 형 인터페이스에서도 어댑터를 분리합니다. 다른 랩핑 패턴보다 복잡성이 증가하므로주의해서 적용하십시오.

생성자의 차이점

생성자를 볼 때 패턴 차이도 분명합니다.

  • 프록시 가 기존 객체를 래핑하지 않습니다. 생성자에는 제목이 없습니다.

  • 데코레이터어댑터 는 기존 객체를 래핑하며 일반적으로
    생성자에서 제공됩니다.

  • Facade 생성자는 전체 객체 그래프의 루트 요소를 사용합니다. 그렇지 않으면 Adapter와 같습니다.

실제 예 – JAXB Marshalling Adapter . 이 어댑터의 목적은 간단한 플랫 클래스를 외부에서 요구되는보다 복잡한 구조에 매핑하고 과도한 주석으로 주제 클래스를 "오염"시키는 것을 방지하는 것입니다.


30

많은 GoF 패턴에는 많은 중복이 있습니다. 그것들은 모두 다형성의 힘을 기반으로하며 때로는 의도 만 다를뿐입니다. (전략 대 상태)

Head First Design Patterns를 읽은 후 패턴에 대한 나의 이해가 100 배 증가했습니다 .

나는 그것을 강력히 추천합니다!


9

전문가의 모든 좋은 답변은 이미 각 패턴의 의미를 설명했습니다.

요점 을 장식 하겠습니다 .

데코레이터 :

  1. 런타임에 객체에 동작 추가 . 상속은이 기능을 달성하는 열쇠이며,이 패턴의 장단점입니다.
  2. 인터페이스 의 동작 을 수정합니다 .

(체인)와 예 : java.io관련된 패키지 클래스 InputStreamOutputStream인터페이스

FileOutputStream fos1 = new FileOutputStream("data1.txt");  
ObjectOutputStream out1 = new ObjectOutputStream(fos1);

대리:

  1. 객체를 캐싱하고 클라이언트 / 호출자에 대한 액세스를 제어하여 지연 초기화, 성능 개선에 사용 . 대체 동작을 제공하거나 실제 객체를 호출 할 수 있습니다. 이 과정에서 새로운 객체가 생성 될 수 있습니다.
  2. 객체 연결을 허용하는 Decorator 와 달리 프록시 는 연결을 허용하지 않습니다.

예 : java.rmi패키지 클래스.

어댑터:

  1. 두 개의 관련되지 않은 인터페이스가 다른 객체를 통해 함께 작동 할 수 있습니다. 동일한 역할을 할 수 있습니다.
  2. 원래 인터페이스를 수정합니다 .

예를 들어, java.io.InputStreamReader( InputStream반환 Reader)

다리:

  1. 추상화와 구현 모두 독립적으로 변할 수있다 .
  2. 상속보다 구성을 사용합니다 .

예를 들어, 컬렉션 수업에서 java.util. List에 의해 구현되었습니다 ArrayList.

주요 사항 :

  1. 어댑터 는 주제와 다른 인터페이스를 제공합니다. 프록시 는 동일한 인터페이스를 제공합니다. Decorator 는 향상된 인터페이스를 제공합니다.
  2. 어댑터 는 객체의 인터페이스를 변경하고 Decorator 는 객체의 책임을 향상시킵니다.
  3. 데코레이터 프록시 는 목적은 다르지만 구조는 비슷합니다
  4. 어댑터 는 디자인 된 후에 작동합니다. Bridge 는 이전에 작동하도록합니다.
  5. Bridge 는 추상화와 구현이 독립적으로 변할 수 있도록 사전에 설계되었습니다. 관련없는 클래스가 함께 작동하도록 어댑터 가 개조되었습니다.
  6. Decorator 는 서브 클래 싱없이 객체에 책임을 추가 할 수 있도록 설계되었습니다.

다양한 디자인 패턴의 예에 관한 훌륭한 SE 질문 / 기사를 살펴보십시오.

데코레이터 패턴을 사용하는시기

브리지 패턴은 언제 사용합니까? 어댑터 패턴과 어떻게 다릅니 까?

프록시와 데코레이터 패턴의 차이점


8

그것들은 매우 비슷하며, 그들 사이의 선은 매우 회색입니다. c2 위키에서 프록시 패턴데코레이터 패턴 항목 을 읽는 것이 좋습니다 .

이 글의 내용과 토론은 매우 광범위하며 다른 관련 기사로 연결됩니다. 그건 그렇고, c2 위키는 다른 패턴 사이의 뉘앙스에 대해 궁금 할 때 탁월합니다.

c2 항목을 요약하면 데코레이터가 동작을 추가 / 변경하지만 프록시는 액세스 제어 (게으른 인스턴스화, 원격 액세스, 보안 등)와 더 관련이 있습니다. 그러나 내가 말했듯이, 그들 사이의 선은 회색이며, 데코레이터로 쉽게 볼 수 있고 그 반대로도 볼 수있는 프록시에 대한 언급이 있습니다.


4

네 가지 패턴은 모두 내부 객체 / 클래스를 외부 패턴으로 감싸는 것을 포함하므로 구조적으로 매우 유사합니다. 목적에 따라 차이점을 설명하겠습니다.

  • 대리 는 외부에서 내부로의 액세스를 캡슐화합니다.
  • 데코레이터 는 외부의 내부 동작을 수정하거나 확장합니다.
  • 어댑터 는 인터페이스를 내부에서 외부로 변환합니다.
  • 브리지 는 가변 동작 부분 (외부)과 가변 또는 플랫폼 종속 부분 (내부)을 분리합니다.

내부 객체와 외부 객체 간의 인터페이스 변형에 따라

  • 에서 프록시 인터페이스는 동일하다.
  • 에서 실내 장식 인터페이스와 동일하다.
  • 어댑터 인터페이스 에서 형식은 다르지만 동일한 목적을 달성하십시오.
  • 에서 브릿지 인터페이스는 다른 개념이다.

4

이것은 Head First Design Patterns 에서 인용 한 것입니다.

정의는 책에 속합니다. 예는 나에게 속한다.

Decorator- 인터페이스를 변경하지 않지만 책임을 추가합니다. 자동차 인터페이스가 있다고 가정하면, 자동차의 다른 모델 (s, sv, sl)에 대해이를 구현할 때 일부 모델에 대해 더 많은 책임추가 해야 할 수도 있습니다 . 선 루프, 에어백 등이 있습니다.

어댑터 -한 인터페이스를 다른 인터페이스로 변환합니다. 자동차 인터페이스가 있으며 지프처럼 작동하기를 원합니다. 그래서 당신은 차를 가지고 수정하고 지프로 변합니다. 실제 지프가 아니기 때문에. 그러나 지프처럼 행동합니다.

Facade- 인터페이스를 더 단순하게 만듭니다. 자동차, 비행기, 선박 인터페이스가 있다고 가정하십시오. 실제로 필요한 것은 한 장소에서 다른 장소로 사람들을 보내는 수업입니다. 어떤 차량을 사용할지 정해야합니다. 그런 다음 하나의 우산 아래에 있는 모든 인터페이스 참조 를 수집 하고 간단하게 결정 / 위임합니다.

Head First : "Facade는 인터페이스를 단순화 할뿐만 아니라 클라이언트를 구성 요소의 하위 시스템에서 분리합니다. Facade 및 어댑터는 여러 클래스를 래핑 할 수 있지만 Façade의 의도는 단순화하는 반면 어댑터는 인터페이스를 다른 것으로 변환하는 것입니다. "


1

웹 서비스를 사용할 때 자주 사용합니다. 프록시 패턴의 이름은 '래퍼 패턴'과 같이보다 실용적인 것으로 바뀌어야하며, MS Excel에 대한 프록시 라이브러리도 있으며, 무엇과 같은 배경 세부 정보에 대해 걱정할 필요없이 Excel을 매우 쉽게 자동화 할 수 있습니다. 버전이 설치되어 있습니다 (있는 경우).


이것이 어댑터 패턴이 아닌가?
Charles Graham

1
웹 서비스는 프록시에 의해 소비되는 반면, 어댑터 패턴은 한 형태에서 다른 형태로 데이터를 변환하거나 변환하는 데 더 많이 사용됩니다.
hmcclungiii 2009

1

세부 구현을 말하면 Proxy와 Decorator, Adapter, Facade의 차이점을 알 수 있습니다 ...이 패턴의 일반적인 구현에는 대상 객체가 둘러싸는 객체로 둘러싸여 있습니다. 클라이언트는 대상 객체 대신 엔 클로징 객체를 사용합니다. 그리고 대상 객체는 실제로 객체를 둘러싸는 일부 방법에서 중요한 부분을 담당합니다.

그러나 프록시의 경우 엔 클로징 오브젝트는 자체적으로 일부 메소드를 재생할 수 있으며 클라이언트가 대상 오브젝트가 참여해야하는 메소드를 호출 할 때 대상 오브젝트를 초기화하기 만합니다. 이는 초기화 지연입니다. 다른 패턴의 경우 둘러싸는 객체는 사실상 대상 객체를 기반으로합니다. 따라서 대상 객체는 항상 생성자 / 설정자에 포함 된 객체와 함께 초기화됩니다.

또 다른 것은 프록시가 대상의 기능을 정확하게 수행하는 반면 다른 패턴은 대상에 더 많은 기능을 추가하는 것입니다.


1

Bill Karwing 답변에 예제를 추가하고 싶습니다 (큰 btw입니다). 구현의 주요 차이점을 추가했습니다.

인용 된 부품은 [ https://stackoverflow.com/a/350471/1984346] (Bill Karwing)

프록시, 데코레이터, 어댑터 및 브리지는 모두 클래스 "래핑"의 변형입니다. 그러나 그들의 용도는 다릅니다.

  • 프록시 는 개체를 지연 인스턴스화하거나 원격 서비스를 호출한다는 사실을 숨기거나 개체에 대한 액세스를 제어하려는 경우에 사용할 수 있습니다.

프록시 된 ProxyClass와 ObjectClass는 동일한 인터페이스를 구현해야합니다.

예-프록시 비싼 객체

class ProxyHumanGenome implements GenomeInterface  {
    private $humanGenome = NULL; 

    // humanGenome class is not instantiated at construct time
    function __construct() {
    }

    function getGenomeCount() {
        if (NULL == $this->humanGenome) {
            $this->instantiateGenomeClass(); 
        }
        return $this->humanGenome->getGenomeCount();
    }
} 
class HumanGenome implement GenomeInterface { ... }
  • 데코레이터 는 "스마트 프록시"라고도합니다. 이것은 객체에 기능을 추가하려고 할 때 사용되지만 해당 객체의 유형을 확장하지는 않습니다. 이를 통해 런타임에 그렇게 할 수 있습니다.

DecoratorClass는 ObjectClass의 확장 인터페이스를 구현할 수 있어야합니다. 따라서 ObjectClass는 DecoratorClass로 대체 될 수 있지만 그 반대는 아닙니다.

예-추가 기능 추가

class DecoratorHumanGenome implements CheckGenomeInterface  {

    // ... same code as previous example

    // added functionality
    public function isComplete() {
        $this->humanGenome->getCount >= 21000
    }
}

interface CheckGenomeInterface extends GenomeInterface {

    public function isComplete();

}

class HumanGenome implement GenomeInterface { ... }
  • 어댑터 는 추상 인터페이스가 있고 해당 인터페이스를 기능적인 역할은 비슷하지만 다른 인터페이스를 가진 다른 객체에 매핑하려고 할 때 사용됩니다.

능력 차이 프록시, 데코레이터, 어댑터

어댑터는 주제와 다른 인터페이스를 제공합니다. 프록시는 동일한 인터페이스를 제공합니다. Decorator는 향상된 인터페이스를 제공합니다.

  • Bridge 는 Adapter와 매우 유사하지만 추상 인터페이스와 기본 구현을 모두 정의 할 때 Bridge라고합니다. 즉, 일부 레거시 또는 타사 코드에 적응하지 않고 모든 코드의 설계자이지만 다른 구현을 바꿀 수 있어야합니다.

  • Facade 는 하나 이상의 클래스 서브 시스템에 대한 상위 레벨 (읽기 : 단순) 인터페이스입니다. 표현하기 위해 여러 객체가 필요한 복잡한 개념이 있다고 가정합니다. 호출해야 할 메소드가있는 오브젝트를 항상 알지 못하기 때문에 해당 오브젝트 세트를 변경하는 것은 혼란 스러울 수 있습니다. 이제 객체 컬렉션에 대해 수행 할 수있는 모든 복잡한 작업에 대해 높은 수준의 방법을 제공하는 Facade를 작성해야합니다. 예 : 같은 방법으로 학교 섹션에 대한 도메인 모델, countStudents(), reportAttendance(), assignSubstituteTeacher(), 등.

이 답변의 대부분의 정보는 https://sourcemaking.com/design_patterns 에서 가져온 것으로, 디자인 패턴에 대한 훌륭한 자료 로 추천 합니다.


0

나는 코드가 명확한 아이디어를 줄 것이라고 생각합니다 (다른 사람들의 답변도 보완하기 위해). 아래를 참조하십시오 (클래스가 구현하고 포장하는 유형에 중점을 둡니다)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            /* Proxy */

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("PROXY");
            Console.WriteLine(Environment.NewLine);

            //instead of creating here create using a factory method, the facory method will return the proxy
            IReal realProxy = new RealProxy();
            Console.WriteLine("calling do work with the proxy object ");
            realProxy.DoWork();

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("ADAPTER");
            Console.WriteLine(Environment.NewLine);

            /*Adapter*/
            IInHand objectIHave = new InHand();
            Api myApi = new Api();
            //myApi.SomeApi(objectIHave); /*I cant do this, use a adapter then */
            IActual myAdaptedObject = new ActualAdapterForInHand(objectIHave);
            Console.WriteLine("calling api with  my adapted obj");
            myApi.SomeApi(myAdaptedObject);


            Console.WriteLine(Environment.NewLine);
            Console.WriteLine("DECORATOR");
            Console.WriteLine(Environment.NewLine);

            /*Decorator*/
            IReady maleReady = new Male();
            Console.WriteLine("now male is going to get ready himself");
            maleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReady = new Female();
            Console.WriteLine("now female is going to get ready her self");
            femaleReady.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady maleReadyByBeautician = new Beautician(maleReady);
            Console.WriteLine("now male is going to get ready by beautician");
            maleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            IReady femaleReadyByBeautician = new Beautician(femaleReady);
            Console.WriteLine("now female is going to get ready by beautician");
            femaleReadyByBeautician.GetReady();

            Console.WriteLine(Environment.NewLine);

            Console.ReadLine();


        }
    }

    /*Proxy*/

    public interface IReal
    {
        void DoWork();
    }

    public class Real : IReal
    {
        public void DoWork()
        {
            Console.WriteLine("real is doing work ");
        }
    }


    public class RealProxy : IReal
    {
        IReal real = new Real();

        public void DoWork()
        {
            real.DoWork();
        }
    }

    /*Adapter*/

    public interface IActual
    {
        void DoWork();
    }

    public class Api
    {
        public void SomeApi(IActual actual)
        {
            actual.DoWork();
        }
    }

    public interface IInHand
    {
        void DoWorkDifferently();
    }

    public class InHand : IInHand
    {
        public void DoWorkDifferently()
        {
            Console.WriteLine("doing work slightly different ");
        }
    }

    public class ActualAdapterForInHand : IActual
    {
        IInHand hand = null;

        public ActualAdapterForInHand()
        {
            hand = new InHand();
        }

        public ActualAdapterForInHand(IInHand hnd)
        {
            hand = hnd;
        }

        public void DoWork()
        {
            hand.DoWorkDifferently();
        }
    }

    /*Decorator*/

    public interface IReady
    {
        void GetReady();
    }

    public class Male : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
        }
    }

    public class Female : IReady
    {
        public void GetReady()
        {
            Console.WriteLine("Taking bath.. ");
            Console.WriteLine("Dress up....");
            Console.WriteLine("Make up....");
        }
    }

    //this is a decorator
    public class Beautician : IReady
    {
        IReady ready = null;

        public Beautician(IReady rdy)
        {
            ready = rdy;
        }

        public void GetReady()
        {
            ready.GetReady();
            Console.WriteLine("Style hair ");

            if (ready is Female)
            {
                for (int i = 1; i <= 10; i++)
                {
                    Console.WriteLine("doing ready process " + i);
                }

            }
        }
    }

}

-3

디자인 패턴은 수학이 아니라 예술과 소프트웨어 공학의 조합입니다. 이 요구 사항에 대해서는 프록시, 브리지 등을 사용해야합니다. 디자인 패턴은 문제를 해결하기 위해 만들어집니다. 디자인 문제가 예상되면 사용하십시오. 경험을 바탕으로 특정 문제, 사용할 패턴에 대해 알게 될 것입니다. 견고한 디자인 원칙을 잘 알고 있다면 패턴을 모른 채 디자인 패턴을 구현했을 것입니다. 일반적인 예는 통계 및 공장 패턴입니다.

따라서 견고한 디자인 원칙, 깨끗한 코딩 원칙 및 TTD에 더 집중


질문에 답하지는 않지만 동의하십시오.
레온
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.