이미 존재하는 객체에 기능을 추가하려면 어떻게해야합니까?


25

일정량의 잘 정의 된 기능을 가진 인터페이스가 있습니다. 의 말을하자:

interface BakeryInterface {
  public function createCookies();
  public function createIceCream();
}

이것은 대부분의 인터페이스 구현에 효과적이지만, 몇 가지 경우 새로운 기능으로 추가하는 것과 같은 새로운 기능을 추가해야합니다 createBrownies(). 이를위한 명백하고 순진한 접근 방식은 인터페이스를 확장하는 것입니다.

interface BrownieBakeryInterface extends BakeryInterface {
  public function createBrownies();
}

그러나 기존 API를 수정하지 않고 새로운 기능을 추가 할 수 없다는 점에서 상당히 큰 단점이 있습니다 (예 : 새 인터페이스를 사용하도록 클래스 변경).

인스턴스화 후 기능을 추가하기 위해 어댑터 를 사용하려고 생각했습니다 .

class BrownieAdapter {
  private brownieBakery;

  public function construct(BakeryInterface bakery) {
    this->brownieBakery = bakery;
  }

  public function createBrownies() {
    /* ... */
  }
}

어느 것이 나를 다음과 같이 그물로 만들 것입니다 :

bakery = new Bakery();
bakery = new BrownieBakery(bakery);
bakery->createBrownies();

이것은 문제에 대한 좋은 해결책처럼 보이지만, 그렇게함으로써 오래된 신들을 깨우고 있는지 궁금합니다. 어댑터가 갈 길입니까? 따라야 할 더 좋은 패턴이 있습니까? 아니면 정말 총알을 물고 원래 인터페이스를 확장해야합니까?


델파이에는 헬퍼 클래스가 있으며, 실제로 수정하지 않고 기존 클래스에 메소드를 추가하는 것과 같습니다. 예를 들어 Delphi는 그래픽 단위에 TBitmap 클래스가 정의되어 있으며, TBitmap에 Flip 함수를 추가하는 도우미 클래스를 만들 수 있습니다. 헬퍼 클래스가 범위 내에있는 한 MyBitmap.Flip을 호출 할 수 있습니다.
Bill

답변:


14

정확한 요구 사항, 언어 및 필요한 추상화 수준에 따라 모든 핸들 바디 패턴 이 설명에 맞을 수 있습니다.

순수한 접근 방식은 Decorator 패턴으로 , 원하는 것을 정확하게 수행하고 객체에 책임을 동적으로 추가합니다. 실제로 빵집을 짓고 있다면 분명히 과잉이며 어댑터를 사용해야합니다.


이것은 내가 필요한 것입니다 : 어댑터를 사용하면 의존성 주입으로 나사를 조일 수 있지만 데코레이터를 사용하면 문제가 해결됩니다.

5

가로 재사용 의 개념을 조사하십시오 . 여기 에서 아직 실험적이지만 이미 입증 된 Aspect Oriented Programming 과 때로는 싫어하는 Mixins 와 같은 것을 찾을 수있는 Traits 와 같은 것을 찾을 수 있습니다 .

클래스에 메소드를 추가하는 직접적인 방법은 프로그래밍 언어에 따라 다릅니다. 루비는 원숭이 패치 를 허용 하지만 클래스가 실제로 존재하지 않는 Javascript의 프로토 타입 기반 상속은 객체를 생성하고 복사하여 계속 추가합니다.

var MyClass = {
    do : function(){...}
};

var MyNewClass = new MyClass;
MyClass.undo = function(){...};


var my_new_object = new MyNewClass;
my_new_object.do();
my_new_object.undo();

마지막으로 리플렉션을 사용 하여 수평 재사용 또는 런타임 "수정"및 클래스 / 객체 동작의 "추가"를 에뮬레이션 할 수 있습니다 .


4

bakery사용자 동작 등에 따라 인스턴스가 동작을 동적으로 변경해야하는 요구 사항이있는 경우 Decorator 패턴으로 이동해야합니다 .

경우 bakery의 행동 동적으로 변경되지 않지만 수정할 수 없습니다 Bakery class(등 외부 API를) 다음은 가야 어댑터 패턴 .

경우 bakery의 행동 동적으로 변경되지 않습니다 당신은 수정할 수 있습니다Bakery class (처음 제안 된) 다음 기존 인터페이스를 확장해야하거나 소개하는 새로운 인터페이스를 BrownieInterface 하고하자 Bakery두 개의 인터페이스 구현 BakeryInterfaceBrownieInterface.
그렇지 않으면 아무런 이유없이 코드에 불필요한 복잡성을 추가 할 수 있습니다 (데코레이터 패턴 사용)!


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