디자인 패턴 중에 Decorator Pattern (Java)

hbull의 이미지

안녕하세요?

Head First Design pattern 보다가 Decorator Pattern 이 이해가 안되 질문 올립니다.

먼저 클래스 구조가

+Beverage
+ Dark Roast(Beverage 서브 클래스)
+ CondimentDecorator(Beverage 서브 추상 클래스)
- Whip (CondimentDecorator 서브 클래스)
- Mocha (CondimentDecorator 서브 클래스)

이렇게 되어 있는데요

Beverage beverage = new DarkRoast();
beverage = new Mocha1(beverage);
beverage = new Mocha2(beverage);
beverage = new Whip(beverage);
println(beverage.cost());

이걸 실행하면 cost 가 mocha, mocha, whip 에 3가지 모두의 메소드가 호출되더군요.
이부분이 대체 이해가 안되네요. 한마디로 beverage 인스턴스가 생성한 세개의 객체를 다 참조 하고 있다는 얘기인가요?
책 본문에서는 저렇게 객체를 생성하면 Mocha1 > Mocha2 > Whip 의 집합관계처럼 된다고 하면서 메소드 호출이 마치 재귀 호출인마냥
Whip.cost -> Mocha2.cost -> Mocha1.cost 이렇게 실행된다고 나와있는데요. 이해가 안되네요.
왜 저렇게 되는거죠?

아래는 소스 코드입니다.

public abstract class Beverage {
String description = "제목 없음";
public String getDescription()
{
return description;
}
public abstract double cost();
}

public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}

public class DarkRoast extends Beverage{
public DarkRoast()
{
description = "the Best DarkRoast Coffee";
}
public double cost()
{
return .20;
}
}

public class Mocha extends CondimentDecorator{
Beverage beverage;

public Mocha(Beverage beverage)
{
this.beverage = beverage;
}
public String getDescription()
{
return beverage.getDescription() + ", Mocha";
}
public double cost()
{
return .20 + beverage.cost();
}

}

public class Whip extends CondimentDecorator{
Beverage beverage;

public Whip(Beverage beverage)
{
this.beverage = beverage;
}
public String getDescription()
{
return beverage.getDescription() + ", Whip";
}
public double cost()
{
return .40 + beverage.cost();
}
}

7339989b62a014c4ce6e31b3540bc7b5f06455024f22753f6235c935e8e5의 이미지

Beverage beverage = new DarkRoast();
beverage = new Mocha1(beverage);
beverage = new Mocha2(beverage);
beverage = new Whip(beverage);
println(beverage.cost());

이걸 다시 써보면

Beverage beverage = new Whip(new Mocha1(new Mocha2(new DarkRoast())));
println(beverage.cost());

---8< 서명 -----------------
애니메이션 감상 기록 http://animeta.net/

unsouled의 이미지

설명하기가 참 애매하긴 한데.. 순서대로 차근차근 생각해보면 어렵지 않습니다.

beverage = new Whip(beverage);
println(beverage.cost());

여기 beverage = new Whip(beverage) 에서 생성자의 인자로 들어가는 beverage 의 타입는 Mocha이고 (Whip도 Mocha도 결국 Beverage 의 서브 클래스죠) 리턴되는 객체의 타입은 Whip입니다.

Whip 생성자에서 this.beverage = beverage 로 인해서 Whip 클래스 멤버인 beverage 의 타입은 Mocha가 됩니다. 그 다음 beverage.cost() 의 메소드를 호출하면 Whip#cost 가 실행됩니다.

return .40 + beverage.cost();

여기서 beverage의 타입은 위에 언급했듯이 Mocha 이고 여기서 다시 Mocha#cost 가 실행되겠죠. 이런 과정을 반복하다보면 어느 정도 실마리가 보일겁니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.