๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐ŸŒˆ Chapter 2: ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

๐Ÿ“š ์˜ํ™” ์˜ˆ๋ฉ” ์‹œ์Šคํ…œโ€‹

๐ŸŽˆ ์š”๊ตฌ์‚ฌํ•ญ ์‚ดํŽด๋ณด๊ธฐโ€‹

  • ์˜จ๋ผ์ธ ์˜ํ™” ์˜ˆ๋งค ์‹œ์Šคํ…œ
  • ์˜ํ™”: ์˜ํ™”์— ๋Œ€ํ•œ ๊ธฐ๋ณธ ์ •๋ณด๋ฅผ ํ‘œํ˜„. (์ œ๋ชฉ, ์ƒ์˜์‹œ๊ฐ„, ๊ฐ€๊ฒฉ ์ •๋ณด)
  • ์ƒ์˜: ์‹ค์ œ๋กœ ๊ด€๊ฐ๋“ค์ด ์˜ํ™”๋ฅผ ๊ด€๋žŒํ•˜๋Š” ์‚ฌ๊ฑด์„ ํ‘œํ˜„ (์ƒ์˜ ์ผ์ž, ์‹œ๊ฐ„, ์ˆœ๋ฒˆ)
  • ํ•˜๋‚˜์˜ ์˜ํ™”๋Š” ํ•˜๋ฃจ ์ค‘ ๋‹ค์–‘ํ•œ ์‹œ๊ฐ„๋Œ€์— ๊ฑธ์ณ ํ•œ ๋ฒˆ ์ด์ƒ ์ƒ์˜
  • ํŠน์ •ํ•œ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์˜ˆ๋งค์ž๋Š” ์š”๊ธˆ์„ ํ• ์ธ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • ํ• ์ธ์•ก์„ ๊ฒฐ์ •ํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๊ทœ์น™
    • ํ• ์ธ ์กฐ๊ฑด: ๊ฐ€๊ฒฉ์˜ ํ• ์ธ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋ฉฐ ์ˆœ์„œ ์กฐ๊ฑด๊ณผ ๊ธฐ๊ฐ„ ์กฐ๊ฑด์ด ์žˆ๋‹ค.
    • ํ• ์ธ ์ •์ฑ…: ํ• ์ธ ์š”๊ธˆ์„ ๊ฒฐ์ •ํ•˜๋ฉฐ ๊ธˆ์•ก ํ• ์ธ ์ •์ฑ…๊ณผ ๋น„์œจ ํ• ์ธ ์ •์ฑ…์ด ์žˆ๋‹ค.
    • ์˜ํ™”๋ณ„๋กœ ํ•˜๋‚˜์˜ ํ• ์ธ ์ •์ฑ…๋งŒ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค. ํ• ์ธ ์ •์ฑ…์„ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ํ• ์ธ ์กฐ๊ฑด์€ ๋‹ค์ˆ˜์˜ ํ• ์ธ ์กฐ๊ฑด์„ ํ•จ๊ป˜ ์ง€์ •๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ˆœ์„œ ์กฐ๊ฑด๊ณผ ๊ธฐ๊ฐ„ ์กฐ๊ฑด์„ ์„ž๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ํ• ์ธ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ• ์ธ ์กฐ๊ฑด๊ณผ ํ• ์ธ ์ •์ฑ…์„ ํ•จ๊ป˜ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
  • ํ• ์ธ ์ •์ฑ…์€ 1์ธ์„ ๊ธฐ์ค€์œผ๋กœ ์ฑ…์ •

๐Ÿ“š ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ–ฅํ•ดโ€‹

๐ŸŽˆ ํ˜‘๋ ฅ, ๊ฐ์ฒด, ํด๋ž˜์Šคโ€‹

  • ๊ฐ์ฒด์ง€ํ–ฅ์€ ๊ฐ์ฒด๋ฅผ ์ง€ํ–ฅํ•˜๋Š” ๊ฒƒ์œผ๋กœ ํด๋ž˜์Šค๋ฅผ ๋จผ์ € ๊ฒฐ์ •ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
  • ์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ ํ•„์š”ํ•œ์ง€๋ฅผ ๊ณ ๋ฏผํ•˜๊ธฐ ์ „์— ์–ด๋–ค ๊ฐ์ฒด๋“ค์ด ํ•„์š”ํ•œ์ง€ ๊ณ ๋ฏผํ•ด์•ผ ํ•œ๋‹ค. ํด๋ž˜์Šค๋Š” ์ƒํƒœ์™€ ํ–‰๋™์„ ๊ณต์œ ํ•˜๋Š” ๊ฐ์ฒด๋“ค์„ ์ถ”์ƒํ™”ํ•œ ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ ์–ด๋–ค ๊ฐ์ฒด๋“ค์ด ์–ด๋–ค ์ƒํƒœ์™€ ํ–‰๋™์„ ๊ฐ€์ง€๋Š”์ง€๋ฅผ ๋จผ์ € ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ฐ์ฒด๋Š” ๋…๋ฆฝ์ ์ธ ์กด์žฌ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํ˜‘๋ ฅํ•˜๋Š” ๊ณต๋™์ฒด์˜ ์ผ์›์œผ๋กœ ๋ด์•ผํ•œ๋‹ค. ๋‹ค๋ฅธ ๊ฐ์ฒด์—๊ฒŒ ๋„์›€์„ ์ฃผ๊ฑฐ๋‚˜ ์˜์กดํ•˜๋ฉด์„œ ์‚ด์•„๊ฐ€๋Š” ํ˜‘๋ ฅ์ ์ธ ์กด์žฌ์ด๋‹ค.

๐ŸŽˆ ๋„๋ฉ”์ธ์˜ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ฅด๋Š” ํ”„๋กœ๊ทธ๋žจ ๊ตฌ์กฐโ€‹

  • ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ถ„์•ผ๋ฅผ ๋„๋ฉ”์ธ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • ํด๋ž˜์Šค์˜ ์ด๋ฆ„์€ ๋Œ€์‘๋˜๋Š” ๋„๋ฉ”์ธ ๊ฐœ๋…์˜ ์ด๋ฆ„๊ณผ ๋™์ผํ•˜๊ฑฐ๋‚˜ ์ ์–ด๋„ ์œ ์‚ฌํ•˜๊ฒŒ ์ง€์–ด์•ผ ํ•œ๋‹ค. (์˜ํ™”๋Š” Movie, ์ƒ์˜์€ Screening..)

๐ŸŽˆ ํด๋ž˜์Šค ๊ตฌํ˜„ํ•˜๊ธฐโ€‹

  • Screening ํด๋ž˜์Šค๋Š” ์‚ฌ์šฉ์ž๋“ค์ด ์˜ˆ๋งคํ•˜๋Š” ๋Œ€์ƒ์ธ ์ƒ์˜์„ ๊ตฌํ˜„ํ•œ๋‹ค. Screening์€ ์ƒ์˜ํ•  ์˜ํ™”, ์ˆœ๋ฒˆ, ์ƒ์˜ ์‹œ์ž‘ ์‹œ๊ฐ„์„ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋กœ ํฌํ•จํ•œ๋‹ค.
public class Screening {
private Movie movie;
private int sequence;
private LocalDateTime whenScreened;

public Screening(Movie movie, int sequence, LocalDateTime whenScreened) {
this.movie = movie;
this.sequence = sequence;
this.whenScreened = whenScreened;
}

public LocalDateTime getStartTime() { // ์ƒ์˜ ์‹œ์ž‘ ์‹œ๊ฐ„
return whenScreened;
}

public boolean isSequence(int sequence) { // ์ˆœ๋ฒˆ์˜ ์ผ์น˜ ์—ฌ๋ถ€ ๊ฒ€์‚ฌ
return this.sequence == sequence;
}

public Money getMovieFee() { // ๊ธฐ๋ณธ ์š”๊ธˆ์„ ๋ฐ˜ํ™˜
return movie.getFee();
}
}
  • ํด๋ž˜์Šค๋Š” ๋‚ด๋ถ€์™€ ์™ธ๋ถ€๋กœ ๊ตฌ๋ถ„๋˜๋ฉฐ ํ›Œ๋ฅญํ•œ ํด๋ž˜์Šค๋ฅผ ์„ค๊ณ„ํ•˜๊ธฐ ์œ„ํ•œ ํ•ต์‹ฌ์€ ์–ด๋–ค ๋ถ€๋ถ„์„ ์™ธ๋ถ€์— ๊ณต๊ฐœํ•˜๊ณ  ์–ด๋–ค ๋ถ€๋ถ„์„ ๊ฐ์ถœ์ง€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • Screening์ฒ˜๋Ÿผ ๊ฐ์ฒด์˜ ์†์„ฑ์— ์ง์ ‘ ์ ‘๊ทผ์„ ๋ง‰๊ณ  ์ ์ ˆํ•œ public ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ฒฝ๊ณ„์˜ ๋ช…ํ™•์„ฑ์ด ๊ฐ์ฒด์˜ ์ž์œจ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚ด๋ถ€์™€ ์™ธ๋ถ€๋ฅผ ๊ตฌ๋ถ„ํ•ด์•ผ ํ•œ๋‹ค. ๋˜ํ•œ, ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ๊ตฌํ˜„์˜ ์ž์œ ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

๐Ÿถ ์ž์œจ์ ์ธ ๊ฐ์ฒดโ€‹

  • ๊ฐ์ฒด๋Š” ์ƒํƒœ์™€ ํ–‰๋™์„ ํ•จ๊ป˜ ๊ฐ€์ง€๋Š” ๋ณตํ•ฉ์ ์ธ ์กด์žฌ์ด๋‹ค.
  • ๊ฒ์ฒด๋Š” ์Šค์Šค๋กœ ํŒ๋‹จํ•˜๊ณ  ํ–‰๋™ํ•˜๋Š” ์ž์œจ์ ์ธ ์กด์žฌ์ด๋‹ค.
  • ๊ฐ์ฒด ์ง€ํ–ฅ์€ ๊ฐ์ฒด๋ผ๋Š” ๋‹จ์œ„ ์•ˆ์— ๋ฐ์ดํ„ฐ์™€ ๊ธฐ๋Šฅ์„ ํ•œ ๋ฉ์–ด๋ฆฌ๋กœ ๋ฌถ์Œ์œผ๋กœ์จ ๋ฌธ์ œ ์˜์—ญ์˜ ์•„์ด๋””์–ด๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ์™€ ๊ธฐ๋Šฅ์„ ๊ฐœ์ฒด ๋‚ด๋ถ€๋กœ ํ•จ๊ป˜ ๋ฌถ๋Š” ๊ฒƒ์„ ์บก์Šํ™”๋ผ๊ณ  ํ•œ๋‹ค.
  • ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋Š” ์ƒํƒœ์™€ ํ–‰๋™์„ ์บก์Šํ™”ํ•˜๊ณ  ๋” ๋‚˜์•„๊ฐ€ ์™ธ๋ถ€์—์„œ์˜ ์ ‘๊ทผ์„ ํ†ต์ œํ•  ์ˆ˜ ์žˆ๋Š” ์ ‘๊ทผ ์ œ์–ด ๋ฉ”์ปค๋‹ˆ์ฆ˜๋„ ํ•จ๊ป˜ ์ œ๊ณตํ•œ๋‹ค. (์ ‘๊ทผ ์ œ์–ด๋ฅผ ์œ„ํ•ด public, private๊ณผ ๊ฐ™์€ ์ ‘๊ทผ ์ˆ˜์ •์ž)
  • ์ ‘๊ทผ์„ ํ†ต์ œํ•˜๋Š” ์ด์œ ๋Š” ๊ฐ์ฒด๋ฅผ ์ž์œจ์ ์ธ ์กด์žฌ๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค.
  • ์บก์Šํ™”์™€ ์ ‘๊ทผ ์ œ์–ด๋Š” ๊ฐ์ฒด๋ฅผ ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆˆ๋‹ค. ํ•˜๋‚˜๋Š” ์™ธ๋ถ€์—์„œ ์ ‘๊ทผ๊ฐ€๋Šฅํ•œ ๋ถ€๋ถ„์œผ๋กœ ์ด๋ฅผ ํผ๋ธ”๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์œ„๋ถ€์—์„œ๋Š” ์ ‘๊ทผ ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ  ์˜ค์ง ๋‚ด๋ถ€์—์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ๋ถ€๋ธ์œผ๋กœ ์ด๋ฅผ ๊ตฌํ˜„์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. (์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ตฌํ˜„์˜ ๋ถ„๋ฆฌ ์›์น™๋Š” ๊ฐ์ฒด์ง€ํ–ฅ์˜ ํ•ต์‹ฌ ์›์น™)

๐Ÿถ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์ž์œ โ€‹

  • ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์—ญํ• ์€ ํด๋ž˜์Šค ์ž‘์„ฑ์ž์™€ ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค.
  • ํด๋ž˜์Šค ์ž‘์„ฑ์ž๋Š” ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ํ”„๋กœ๊ทธ๋žจ์— ์ถ”๊ฐ€ํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ํด๋ž˜์Šค ์ž‘์„ฑ์ž๊ฐ€ ์ถ”๊ฐ€ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • ํด๋ž˜์Šค ์ž‘์„ฑ์ž๋Š” ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ํ•„์š”ํ•œ ๋ถ€๋ถ„๋งŒ ๊ณต๊ฐœํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๊ฝ๊ฝ ์ˆจ๊ฒจ์•ผ ํ•œ๋‹ค. (๊ตฌํ˜„ ์€๋‹‰)
  • ์ ‘๊ทผ ์ œ์–ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€์™€ ์™ธ๋ถ€๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๊ฒฝ๊ณ„ ์ง€์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋™์‹œ์— ํด๋ž˜์Šค ์ž‘์„ฑ์ž๊ฐ€ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ์€๋‹‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
  • ๊ตฌํ˜„ ์€๋‹‰์˜ ์žฅ์ ์€ ํด๋ผ์ด์–ธํŠธ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋ชจ๋ฅด๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ์•Œ๊ณ  ์žˆ์–ด๋„ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๊ณ , ํด๋ž˜์Šค ์ž‘์„ฑ์ž๋Š” ์™ธ๋ถ€์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์„ ๊ฑฑ์ •ํ•˜์ง€ ์•Š๊ณ ๋„ ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋งˆ์Œ๋Œ€๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์„ธ๋ถ€์ ์ธ ๊ตฌํ˜„ ๋‚ด์šฉ์„ private ์˜์—ญ ์•ˆ์— ๊ฐ์ถค์œผ๋กœ์จ ๋ณ€๊ฒฝ์œผ๋กœ ์ธํ•œ ํ˜ผ๋ž€์„ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐ŸŽˆ ํ˜‘๋ ฅํ•˜๋Š” ๊ฐ์ฒด๋“ค์˜ ๊ณต๋™์ฒดโ€‹

  • ์˜ํ™”๋ฅผ ์˜ˆ๋งคํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ดํŽด๋ณด์ž.
public class Screening {
// ์˜ํ™”๋ฅผ ์˜ˆ๋งคํ•œ ํ›„ ์˜ˆ๋งค ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” Reservation์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
// reserve(์˜ˆ๋งค์ž ์ •๋ณด, ์ธ์›์ˆ˜)
// calculateFee๋Š” ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•œ ํ›„ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
public Reservation reserve(Customer customer, int audienceCount) {
return new Reservation(customer, this, calculateFee(audienceCount), audienceCount);
}

private Money calculateFee(int audienceCount) {
// calculateMovieFee ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ 1์ธ๋‹น ์˜ˆ๋งค ์š”๊ธˆ์ด๋‹ค.
return movie.calculateMovieFee(this).times(audienceCount);
}
}
  • Screening์€ ์ „์ฒด ์˜ˆ๋งค ์š”๊ธˆ์„ ๊ตฌํ•˜๊ธฐ ์œ„ํ•ด calculateMovieFee ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์— ์ธ์› ์ˆ˜์ธ audienceCount๋ฅผ ๊ณฑํ•œ๋‹ค.
  • Money๋Š” ๊ธˆ์•ก๊ณผ ๊ด€๋ จ๋œ ๋‹ค์–‘ํ•œ ๊ณ„์‚ฐ์„ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค์ด๋‹ค.
public class Money {
public static final Money ZERO = Money.wons(0);

private final BigDecimal amount;

public static Money wons(long amount) {
return new Money(BigDecimal.valueOf(amount));
}

//์ƒ๋žต..
// Money.java ์ฐธ๊ณ ..
}
  • Reservation ํด๋ž˜์Šค์ด๋‹ค.
public class Reservation {
private Customer customer; // ๊ณ ๊ฐ
private Screening screening; // ์ƒ์˜ ์ •๋ณด
private Money fee; // ์˜ˆ๋งค ์š”๊ธˆ
private int audienceCount; // ์ธ์› ์ˆ˜

public Reservation(Customer customer, Screening screening, Money fee, int audienceCount) {
this.customer = customer;
this.screening = screening;
this.fee = fee;
this.audienceCount = audienceCount;
}
}
  • ์˜ํ™”๋ฅผ ์—๋งคํ•˜๊ธฐ ์œ„ํ•ด Screening, Movie, Reservation ์ธ์Šคํ„ด์Šค๋“ค์€ ์„œ๋กœ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ ์ƒํ˜ธ์ž‘์šฉํ•œ๋‹ค. ์ด์ฒ˜๋Ÿผ ์‹œ์Šคํ…œ์˜ ์–ด๋–ค ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ์ฒด๋“ค ์‚ฌ์ด์— ์ด๋ค„์ง€๋Š” ์ƒํ˜ธ์ž‘์šฉ์„ ํ˜‘๋ ฅ(Collaboration)์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ๋•Œ๋Š” ๋จผ์ € ํ˜‘๋ ฅ์˜ ๊ด€์ ์—์„œ ์–ด๋–ค ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•œ์ง€๋ฅผ ๊ฒฐ์ •ํ•˜๊ณ , ๊ฐ์ฒด๋“ค์˜ ๊ณตํ†ต ์ƒํƒœ์™€ ํ–‰์œ„๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

๐ŸŽˆ ํ˜‘๋ ฅ์— ๊ด€ํ•œ ์งง์€ ์ด์•ผ๊ธฐโ€‹

  • ๊ฐ์ฒด๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด์˜ ์ธํ„ฐํŽ˜์ด์Šค์— ๊ณต๊ฐœ๋œ ํ–‰๋™์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ์š”์ฒญํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์š”์ฒญ์„ ๋ฐ›์€ ๊ฐ์ฒด๋Š” ์ž์œจ์ ์ธ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ ํ›„ ์‘๋‹ตํ•œ๋‹ค.
  • ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด์™€ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๋Š” ๊ฒƒ๋ฟ์ด๋‹ค.
  • ๋‹ค๋ฅธ ๊ฐ์ฒด์—๊ฒŒ ์š”์ฒญ์ด ๋„์ฐฉํ•  ๋•Œ ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ–ˆ๋‹ค๊ณ  ์ด์•ผ๊ธฐ ํ•œ๋‹ค.
  • ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•œ ๊ฐ์ฒด๋Š” ์Šค์Šค๋กœ์˜ ๊ฒฐ์ •์— ๋”ฐ๋ผ ์ž์œจ์ ์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ฒ˜๋ฆฌํ•  ๋ฐฉ๋ฒ•์„ ๊ฒฐ์ •ํ•˜๋Š”๋ฐ ์ด๋Ÿฐ ๋ฐฉ๋ฒ„๋ธ” ๋ฉ”์„œ๋“œ๋ผ๊ณ  ํ•œ๋‹ค.
  • ๋ฉ”์‹œ์ง€์™€ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์€ ์ค‘์š”ํ•œ๋ฐ ๋‹คํ˜•์„ฑ์˜ ๊ฐœ๋…์—์„œ ์‹œ์ž‘๋œ๋‹ค.

๐Ÿ“š ํ• ์ธ ์š”๊ธˆ ๊ตฌํ•˜๊ธฐโ€‹

๐ŸŽˆ ํ• ์ธ ์š”๊ธˆ ๊ณ„์‚ฐ์„ ์œ„ํ•œ ํ˜‘๋ ฅ ์‹œ์ž‘ํ•˜๊ธฐโ€‹

public class Movie {
private String title; // ์ œ๋ชฉ
private Duration runningTime; // ์ƒ์˜์‹œ๊ฐ„
private Money fee; // ๊ธฐ๋ณธ ์š”๊ธˆ
private DiscountPolicy discountPolicy; // ํ• ์ธ ์ •์ฑ…

public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) { // ์ƒ์„ฑ์ž
this.title = title;
this.runningTime = runningTime;
this.fee = fee;
this.discountPolicy = discountPolicy;
}

public Money getFee() {
return fee;
}

public Money calculateMovieFee(Screening screening) {
return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
}
  • calculateMovieFee ๋ฉ”์„œ๋“œ๋Š” discountPolicy์— calculateDiscountAmount ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•ด ํ• ์ธ ์š”๊ธˆ์„ ๋ฐ˜ํ™˜๋ฐ›๋Š”๋‹ค. Movie๋Š” ๊ธฐ๋ณธ์š”๊ธˆ์ธ fee์—์„œ ๋ฐ˜ํ™˜๋œ ํ• ์ธ ์š”๊ธˆ์„ ์ฐจ๊ฐํ•œ๋‹ค.
  • ์ด ์ฝ”๋“œ์—์„œ ๊ฐ์ฒด์ง€ํ–ฅ์—์„œ ์ค‘์š”ํ•œ ๋‘ ๊ฐœ๋…์ด ์ˆจ๊ฒจ์ ธ ์žˆ๋Š”๋ฐ ํ•˜๋‚˜๋Š” ์ƒ์†์ด๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๋‹คํ˜•์„ฑ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ธฐ๋ฐ˜์—๋Š” ์ถ”์ƒํ™”๋ผ๋Š” ์›๋ฆฌ๊ฐ€ ์ˆจ๊ฒจ์ ธ ์žˆ๋‹ค.

๐ŸŽˆ ํ• ์ธ ์ •์ฑ…๊ณผ ํ• ์ธ ์กฐ๊ฑดโ€‹

  • ํ• ์ธ ์ •์ฑ…์€ ๊ธˆ์•ก ํ• ์ธ ์ •์ฑ…์ธ AmountDiscountPolicy ํด๋ž˜์Šค์™€ ๋น„์œจ ํ• ์ธ ์ •์ฑ…์ธ PercentDiscountPolicy๋ผ๋Š” ํด๋ž˜์Šค๋กœ ๊ตฌ๋ถ„๋œ๋‹ค.
  • ๋‘ ํด๋ž˜์Šค๋Š” ๋Œ€๋ถ€๋ถ„ใ…‡๋Šฌ ์ฝ”๋“œ๊ฐ€ ์œ ์‚ฌํ•˜๊ณ  ํ• ์ธ ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉ์‹์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ์ œ๊ฑฐํ•˜๊ธฐ ์œ„ํ•ด ๋ถ€๋ชจ ํด๋ž˜์Šค์ธ DiscountPolicy๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ค‘๋ณต ์ฝ”๋“œ๋ฅผ ๋‘˜ ์ˆ˜ ์žˆ๋‹ค.
  • AmountDiscountPolicy์™€ PercentDiscountPolicy๊ฐ€ ์ด ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๊ฒŒ ๋œ๋‹ค. DiscountPolicy์˜ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.
public abstract class DiscountPolicy {
private List<DiscountCondition> conditions = new ArrayList<>();

public DiscountPolicy(DiscountCondition ... conditions) {
this.conditions = Arrays.asList(conditions);
}

public Money calculateDiscountAmount(Screening screening) {
for (DiscountCondition each : conditions) {
if (each.isSatisfiedBy(screening)) {
return getDiscountAmount(screening);
}
}

return Money.ZERO;
}

abstract protected Money getDiscountAmount(Screening screening);
}
  • DiscountCondition์˜ ๋ฆฌ์ŠคํŠธ์ธ conditions๋ฅผ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋กœ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ํ•˜๋‚˜์˜ ํ• ์ธ ์ •์ฑ…์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ• ์ธ ์กฐ๊ฑด์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.
  • calculateDiscountAmount ๋ฉ”์„œ๋“œ๋Š” ์ „์ฒด ํ• ์ธ ์กฐ๊ฑด์— ๋Œ€ํ•ด ์ฐจ๋ก€๋Œ€๋กœ DiscountCondition์˜ isSatisfiedBy ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  isSatisfiedBy ๋ฉ”์„œ๋“œ๋Š” ์ธ์ž๋กœ ์ „๋‹ฌ๋œ Screening์ด ํ• ์ธ ์กฐ๊ฑด์„ ๋งŒ์กฑ์‹œํ‚ฌ ๊ฒฝ์šฐ์—๋Š” true๋ฅผ, ๋งŒ์กฑ์‹œํ‚ค์ง€ ๋ชปํ•  ๊ฒฝ์šฐ์—๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ํ•˜๋‚˜๋ผ๋„ ๋งŒ์กฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ถ”์ƒ ๋ฉ”์„œ๋“œ์ธ getDiscountAmount ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ํ• ์ธ ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•œ๋‹ค. ๋งŒ์กฑํ•˜๋Š” ์กฐ๊ฑด์ด ์—†์„ ๋•Œ ํ• ์ธ ์š”๊ธˆ์œผ๋กœ 0์›์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ์‹ค์ œ ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•˜๋Š” ๋ถ€๋ถ„์€ DiscountPolicy๋ฅผ ์ƒ์† ๋ฐ›๋Š” ์ž์‹ ํด๋ž˜์Šค์—์„œ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•œ ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค.
  • ์ด์ฒ˜๋Ÿผ ๋ถ€๋ชจ ํด๋ž˜์Šค์— ๊ธฐ๋ณธ์ ์ธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ํ๋ฆ„์„ ๊ตฌํ˜„ํ•˜๊ณ  ์ค‘๊ฐ„์— ํ•„์š”ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ž์‹ ํด๋ž˜์Šค์—๊ฒŒ ์œ„์ž„ํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์„ TEMPLATE METHOD ํŒจํ„ด์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • DiscountCondition์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ์„ ์–ธ๋˜์–ด ์žˆ๋‹ค. isSatisfiedBy ๋ฉ”์„œ๋“œ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ screening์ด ํ• ์ธ์ด ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋ฅผ true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
public interface DiscountCondition {
boolean isSatisfiedBy(Screening screening);
}
  • ์˜ํ™” ์˜ˆ๋งค ์‹œ์Šคํ…œ์—๋Š” ์ˆœ๋ฒˆ ์กฐ๊ฑด๊ณผ ๊ธฐ๊ฐ„ ์กฐ๊ฑด์˜ ๋‘ ๊ฐ€์ง€ ํ• ์ธ ์กฐ๊ฑด์ด ์กด์žฌํ•œ๋‹ค. ๋‘ ๊ฐ€์ง€ ํ• ์ธ ์กฐ๊ฑด์€ ๊ฐ๊ฐ SequenceCondition๊ณผ PeriodCondition ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.
public class SequenceCondition implements DiscountCondition {
private int sequence; // ์ˆœ๋ฒˆ

public SequenceCondition(int sequence) {
this.sequence = sequence;
}

public boolean isSatisfiedBy(Screening screening) {
return screening.isSequence(sequence); // ์ƒ์˜ ์ˆœ๋ฒˆ๊ณผ ์ผ์น˜ํ•  ๊ฒฝ์šฐ true, ์ผ์น˜ํ•˜์ง€ ์•Š์œผ๋ฉด false
}
}
  • PeriodCondition์€ ์ƒ์˜ ์‹œ์ž‘ ์‹œ๊ฐ„์ด ํŠน์ •ํ•œ ๊ธฐ๊ฐ„ ์•ˆ์— ํฌํ•จ๋˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹คํ•ด ํ• ์ธ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค.
public class PeriodCondition implements DiscountCondition {
private DayOfWeek dayOfWeek; // ์š”์ผ
private LocalTime startTime; // ์‹œ์ž‘ ์‹œ๊ฐ„
private LocalTime endTime; // ์ข…๋ฃŒ ์‹œ๊ฐ„

public PeriodCondition(DayOfWeek dayOfWeek, LocalTime startTime, LocalTime endTime) {
this.dayOfWeek = dayOfWeek;
this.startTime = startTime;
this.endTime = endTime;
}

// ์ƒ์˜ ์š”์ผ์ด dayOfWeek์™€ ๊ฐ™๊ณ  ์ƒ์˜ ์‹œ์ž‘ ์‹œ๊ฐ„์ด startTime๊ณผ endTime ์‚ฌ์ด์— ์žˆ์„ ๊ฒฝ์šฐ์—๋Š” true
public boolean isSatisfiedBy(Screening screening) {
return screening.getStartTime().getDayOfWeek().equals(dayOfWeek) &&
startTime.compareTo(screening.getStartTime().toLocalTime()) <= 0 &&
endTime.compareTo(screening.getStartTime().toLocalTime()) >= 0;
}
}
  • ์ด์ œ ํ• ์ธ ์ •์ฑ…์„ ๊ตฌํ˜„ํ•œ๋‹ค. ํ• ์ธ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๊ฒฝ์šฐ ์ผ์ •ํ•œ ๊ธˆ์•ก์„ ํ• ์ธํ•ด์ค€๋‹ค.
public class AmountDiscountPolicy extends DiscountPolicy {
private Money discountAmount;

public AmountDiscountPolicy(Money discountAmount, DiscountCondition ... conditions) {
super(conditions);
this.discountAmount = discountAmount;
}

// DiscountPolicy์˜ getDiscountAmount ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•œ๋‹ค.
@Override
protected Money getDiscountAmount(Screening screening) {
return discountAmount;
}
}
  • PercentDiscountPolicy ์—ญ์‹œ DiscountPolicy์˜ ์ž์‹ ํด๋ž˜์Šค๋กœ์„œ getDiscountAmount ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•œ๋‹ค.
  • ํ• ์ธ ๋น„์œจ์„ ์ฐจ๊ฐํ•œ๋‹ค.
public class PercentDiscountPolicy extends DiscountPolicy {
private double percent;

public AmountDiscountPolicy(double percent, DiscountCondition ... conditions) {
super(conditions);
this.percent = percent;
}

@Override
protected Money getDiscountAmount(Screening screening) {
return screening.getMovieFee().times(percent);
}
}
  • ์˜ค๋ฒ„๋ผ์ด๋”ฉ์€ ๋ถ€๋ชจ ํด๋ž˜์Šค์— ์ •์˜๋œ ๊ฐ™์€ ์ด๋ฆ„, ๊ฐ™์€ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ชฉ๋ก์„ ๊ฐ€์ง„ ๋ฉ”์„œ๋“œ๋ฅผ ์ž์‹ ํด๋ž˜์Šค์—์„œ ์žฌ์ •์˜ํ•œ๋‹ค.
  • ์˜ค๋ฒ„๋กœ๋”ฉ์€ ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์€ ๊ฐ™์ง€๋งŒ ์ œ๊ณต๋˜๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๋ชฉ๋ก์ด ๋‹ค๋ฅด๋‹ค.

๐ŸŽˆ ํ• ์ธ ์ •์ฑ… ๊ตฌ์„ฑํ•˜๊ธฐโ€‹

  • ํ• ์€ ์ •์ฑ…์€ ํ•˜๋‚˜๋งŒ ์„ค์ •ํ•˜๊ณ  ํ• ์ธ ์กฐ๊ฑด์€ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. Movie์™€ DiscountPolicy์˜ ์ƒ์„ฑ์ž๋Š” ์ด๋Ÿฐ ์ œ์•ฝ์„ ๊ฐ•์ œํ•œ๋‹ค.
public class Movie {
// ...

public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {
// ...
this.discountPolicy = discountPolicy;
}

// ...
}
  • DiscountPolicy์˜ ์ƒ์„ฑ์ž๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ DiscountCondition ์ธ์Šคํ„ด์Šค๋ฅผ ํ—ˆ์šฉํ•œ๋‹ค.
public abstract class DiscountPolicy {
// ...

public DiscountPolicy(DiscountCondition ... conditions) {
this.conditions = Arrays.asList(conditions);
}

// ...
}
  • ์ด์ฒ˜๋Ÿผ ์ƒ์„ฑ์ž์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ชฉ๋กœ์„ ์ด์šฉํ•ด ์ดˆ๊ธฐํ™”์— ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ „๋‹ฌํ•˜๋„๋ก ๊ฐ•์ œํ•˜๋ฉด ์˜ฌ๋ฐ”๋ฅธ ์ƒํƒœ๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ• ์ธ ์ •์ฑ…๊ณผ ํ• ์ธ ์กฐ๊ฑด์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
Movie avatar = new Movie("์•„๋ฐ”ํƒ€",
Duration.ofMinutes(120),
Money.wons(10000),
new AmountDiscountPolicy(Money.wons(800),
new SequenceCondition(1),
new SequenceCondition(10),
new PeriodCondition(DayOfWeek.MONDAY, LocalTime.of(10, 0), LocalTime.of(11, 59)),
new PeriodCondition(DayOfWeek.THURSDAY, LocalTime.of(10, 0), LocalTime.of(20, 59))
)
);

๐Ÿ“š ์ƒ์†๊ณผ ๋‹คํ˜•์„ฑโ€‹

๐ŸŽˆ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ์˜์กด์„ฑ๊ณผ ์‹คํ–‰ ์‹œ๊ฐ„ ์˜์กด์„ฑโ€‹

  • Movie ํด๋ž˜์Šค๋Š” ์ฝ”๋“œ ์ˆ˜์ค€์—์„œ AmountDiscountPolicy๋‚˜ PercentDiscountPolicy์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ์˜ค์ง ์ถ”์ƒ ํด๋ž˜์Šค์ธ DiscountPolicy์—๋งŒ ์˜์กดํ•œ๋‹ค.
  • ๋งŒ์•ฝ ์˜ํ™” ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด ๊ธˆ์•ก ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด Movie์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์ธ์ž๋กœ AmountDiscountPolicy์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋œ๋‹ค. ์ด์ œ ์‹คํ–‰ ์‹œ์— Movie์˜ ์ธ์Šคํ„ด์Šค๋Š” AmountDiscountPolicy ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค์— ์˜์กดํ•˜๊ฒŒ ๋œ๋‹ค.
  • ์ด์ฒ˜๋Ÿผ ์‹คํ–‰ ์‹œ์ ์—๋Š” Movie์˜ ์ธ์Šคํ„ด์Šค๋Š” AmountDiscountPolicy๋‚˜ PercentDiscountPolicy์˜ ์ธ์Šคํ„ด์Šค์— ์˜์กดํ•˜๊ฒŒ ๋œ๋‹ค.
  • ์œ ์—ฐํ•˜๊ณ , ์‰ฝ๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„๊ฐ€ ๊ฐ€์ง€๋Š” ํŠน์ง•์€ ์ฝ”๋“œ์˜ ์˜์กด์„ฑ๊ณผ ์‹คํ–‰ ์‹œ์ ์˜ ์˜์กด์„ฑ์ด ๋‹ค๋ฅด๋‹ค๋Š” ์ ์ด๋‹ค. ๋‹จ์ ์€ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง„๋‹ค. ์„ค๊ณ„๊ฐ€ ์œ ์—ฐํ•ด์งˆ์ˆ˜๋ก ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ณ  ๋””๋ฒ„๊น…ํ•˜๊ธฐ๋Š” ์ ์  ๋” ์–ด๋ ค์›Œ์ง„๋‹ค. ๋ฐ˜๋ฉด ์œ ์—ฐ์„ฑ์„ ์–ต์ œํ•˜๋ฉด ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ํ™•์žฅ ๊ฐ€๋Šฅ์„ฑ์€ ๋‚ฎ์•„์ง„๋‹ค.

๐ŸŽˆ ์ฐจ์ด์— ์˜ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐโ€‹

  • ์ƒ์†์€ ๊ฐ์ฒด์ง€ํ–ฅ์—์„œ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์žฅ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
  • ์ƒ์†์„ ์ด์šฉํ•˜๋ฉด ํด๋ž˜์Šค ์‚ฌ์ด์— ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ํด๋ž˜์Šค๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ชจ๋“  ์†์„ฑ๊ณผ ํ–‰๋™์„ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค์— ํฌํ•จ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ๋‹ค๋ฅธ ๋ถ€๋ถ„๋งŒ์„ ์ถ”๊ฐ€ํ•ด์„œ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐจ์ด์— ์˜ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

๐ŸŽˆ ์ƒ์†๊ณผ ์ธํ„ฐํŽ˜์ด์Šคโ€‹

  • ์ƒ์†์ด ๊ฐ€์น˜ ์žˆ๋Š” ์ด์œ ๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“  ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๋ฌผ๋ ค๋ฐ›์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ์ฒด๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์‹œ์ง€์˜ ๋ชฉ๋ก์„ ์ •์˜ํ•œ๋‹ค.
  • ์ƒ์†์„ ํ†ตํ•ด ์ž์‹ ํด๋ž˜์Šค๋Š” ์ž์‹ ์˜ ์ธํ„ฐํŽ˜์ด์Šค์— ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํฌํ•จํ•˜๊ฒŒ ๋œ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ž์‹ ํด๋ž˜์Šค๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค๊ฐ€ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์™ธ๋ถ€ ๊ฐ์ฒด๋Š” ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ๋™์ผํ•œ ํƒ€์ž…์œผ๋กœ ๊ฐ„์ฃผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค์‹œ ๋งํ•ด์„œ ์ž์‹ ํด๋ž˜์Šค๋Š” ์ƒ์†์„ ํ†ตํ•ด ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฌผ๋ ค๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€๋ชจ ํด๋ž˜์Šค ๋Œ€์‹  ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด์ฒ˜๋Ÿผ ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ๋Œ€์‹ ํ•˜๋Š” ๊ฒƒ์„ ์—…์บ์ŠคํŒ…์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

๐ŸŽˆ ๋‹คํ˜•์„ฑโ€‹

  • ์ฝ”๋“œ ์ƒ์—์„œ Movie ํด๋ž˜์Šค๋Š” DiscountPolicy ํด๋ž˜์Šค์—๊ฒŒ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜์ง€๋งŒ ์‹คํ–‰ ์‹œ์ ์— ์‹ค์ œ๋กœ ์‹คํ–‰๋˜๋Š” ๋ฉ”์„œ๋“œ๋Š” Movie์™€ ํ˜‘๋ ฅํ•˜๋Š” ๊ฐ์ฒด์˜ ์‹ค์ œ ํด๋ž˜์Šค๊ฐ€ ๋ฌด์—‡์ธ์ง€์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค. ๋‹ค์‹œ ๋งํ•ด์„œ Movie๋Š” ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ ์–ด๋–ค ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋  ๊ฒƒ์ธ์ง€๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๊ฐ€ ๋ฌด์—‡์ด๋ƒ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง„๋‹ค. ์ด๋ฅผ ๋‹คํ˜•์„ฑ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • ๋‹คํ˜•์„ฑ์€ ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋žจ์˜ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ์˜์กด์„ฑ๊ณผ ์‹คํ–‰ ์‹œ๊ฐ„ ์˜์กด์„ฑ์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.
  • ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑํ•  ๋•Œ Movie๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์ธ DiscountPolicy์— ์˜์กดํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ ์˜์กด์„ฑ์€ DiscountPolicy๋กœ ํ–ฅํ•œ๋‹ค. ๋ฐ˜๋ฉด์— ์‹คํ–‰ ์‹œ์ ์€ ์‹ค์ œ๋กœ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๊ฐ์ฒด๋Š” AmountDiscountPolicy๋˜๋Š” PercentDiscountPolicy์˜ ์ธ์Šคํ„ด์Šค์ด๋‹ค. ๋‹ค์‹œ ๋งํ•ด ์‹คํ–‰ ์‹œ๊ฐ„ ์˜์กด์„ฑ์€ AmountDiscountPolicy๋‚˜ PercentDiscountPolicy๋กœ ํ–ฅํ•œ๋‹ค.
  • ๋‹คํ˜•์„ฑ์ด๋ž€ ๋™์ผํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ–ˆ์„ ๋•Œ ๊ฐ์ฒด์˜ ํƒ€์ž…์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ์˜๋ฏธํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹คํ˜•์ ์ธ ํ˜‘๋ ฅ์— ์ฐธ์—ฌํ•˜๋Š” ๊ฐ์ฒด๋Š” ๋ชจ๋‘ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ๋‹ค์‹œ ๋งํ•ด ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋™์ผํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ๋ฉ”์‹œ์ง€์™€ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ ์‹œ์ ์— ๋ฐ”์ธ๋”ฉํ•œ๋‹ค. ์ด๋ฅผ ์ง€์—ฐ ๋ฐ”์ธ๋”ฉ ๋˜๋Š” ๋™์  ๋ฐ”์ธ๋”ฉ์ด๋ผ๊ณ  ํ•œ๋‹ค.
  • ๊ทธ์— ๋ฐ˜ํ•ด ์ „ํ†ต์ ์ธ ํ•จ์ˆ˜ ํ˜ธ์ถœ์ฒ˜๋Ÿผ ์ปดํŒŒ์ผ ์‹œ์ ์— ์‹คํ–‰๋  ํ•จ์ˆ˜๋‚˜ ํ”„๋กœ์‹œ์ €๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์„ ์ดˆ๊ธฐ ๋ฐ”์ธ๋”ฉ ๋˜๋Š” ์ •์  ๋ฐ”์ธ๋”ฉ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • ๊ฐ์ฒด์ง€ํ–ฅ์ด ์ปดํŒŒ์ผ ์‹œ์ ์˜ ์˜์กด์„ฑ๊ณผ ์‹คํ–‰ ์‹œ์ ์˜ ์˜์กด์„ฑ์„ ๋ถ„๋ฆฌํ•˜๊ณ , ํ•˜๋‚˜์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์„ ํƒ์ ์œผ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์ด์œ ๊ฐ€ ์ง€์—ฐ ๋ฐ”์ธ๋”ฉ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๐ŸŽˆ ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋‹คํ˜•์„ฑโ€‹

  • ์ž๋ฐ”์˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌํ˜„์— ๋Œ€ํ•œ ๊ณ ๋ ค ์—†์ด ๋‹คํ˜•์ ์ธ ํ˜‘๋ ฅ์— ์ฐธ์—ฌํ•˜๋Š” ํด๋ž˜์Šค๋“ค์ด ๊ณต์œ  ๊ฐ€๋Šฅํ•œ ์™ธ๋ถ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•œ ๊ฒƒ์ด๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ถ”์ƒ ํด๋ž˜์Šค์™€ ๋‹ฌ๋ฆฌ ๊ตฌํ˜„์„ ๊ณต์œ ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

๐Ÿ“š ์ถ”์ƒํ™”์™€ ์œ ์—ฐ์„ฑโ€‹

๐ŸŽˆ ์ถ”์ƒํ™”์˜ ํž˜โ€‹

  • DiscountPolicy๋Š” AmountDiscountPolicy์™€ PercentDiscountPolicy๋ณด๋‹ค ์ถ”์ƒ์ ์ด๊ณ  DiscountCondition์€ SequenceCondition์™€ PeriodCondition ๋ณด๋‹ค ๋” ์ถ”์ƒ์ ์ด๋‹ค.
  • ๋” ์ถ”์ƒ์ ์ธ ์ด์œ ๋Š” ์ธํ„ฐํŽ˜์ด์Šค์— ์ดˆ์ ์„ ๋งŸ์ถ”๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. DiscountPolicy๋Š” ๋ชจ๋“  ํ• ์ธ ์ •์ฑ…๋“ค์ด ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋Š” calculateDiscountAmount ๋ฉ”์‹œ์ง€๋ฅผ ์ •์˜ํ•œ๋‹ค. DiscountCondition์€ ๋ชจ๋“  ํ• ์ธ ์กฐ๊ฑด๋“ค์ด ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋Š” isSatisfiedBy ๋ฉ”์‹œ์ง€๋ฅผ ์ •์˜ํ•œ๋‹ค.
  • ๊ตฌํ˜„์„ ์ž์‹  ํด๋ž˜์Šค๊ฐ€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฒฐ์ •๊ถŒ์„ ์œ„์ž„ํ•œ๋‹ค.
  • ์ถ”์ƒํ™”์˜ ์žฅ์ ์€ ์š”๊ตฌ์‚ฌํ•ญ์˜ ์ •์ฑ…์„ ๋†’์€ ์ˆ˜์ค€์—์„œ ์„œ์ˆ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ์žฅ์ ์€ ์ถ”์ƒํ™”๋ฅผ ์ด์šฉํ•˜๋ฉด ์„ค๊ณ„๊ฐ€ ์ข€ ๋” ์œ ์—ฐํ•ด์ง„๋‹ค.

๐ŸŽˆ ์œ ์—ฐํ•œ ์„ค๊ณ„โ€‹

  • ๋งŒ์•ฝ ํ• ์ธ ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•  ํ•„์š” ์—†์ด ์˜ํ™”์— ์„ค์ •๋œ ๊ธฐ๋ณธ ๊ธˆ์•ก์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•  ๋• ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
public class Movie {
public Money calculateMovieFee(Screening screening) {
if (discountPolicy == null) {
return fee;
}

return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
}
  • ์œ„์™€ ๊ฐ™์ด ํ•˜๋ฉด ๋ ๊นŒ? ํ•˜์ง€๋งŒ ์ด ๊ฒฝ์šฐ ์˜ˆ์™ธ ์ผ€์ด์Šค๋กœ ์ทจ๊ธ‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ง€๊ธˆ๊นŒ์ง€ ์ผ๊ด€์„ฑ ์žˆ๋˜ ํ˜‘๋ ฅ ๋ฐฉ์‹์ด ๋ฌด๋„ˆ์ง€๊ฒŒ ๋œ๋‹ค.
  • ์ฑ…์ž„์˜ ์œ„์น˜๋ฅผ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด ์กฐ๊ฑด๋ฌธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ํ˜‘๋ ฅ์˜ ์„ค๊ณ„ ์ธก๋ฉด์—์„œ ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ ์ข‹์ง€ ์•Š์€ ์„ ํƒ์ด๋‹ค. ํ•ญ์ƒ ์˜ˆ์™ธ ์ผ€์ด์Šค๋ฅผ ์ตœ์†Œํ™”ํ•˜๊ณ  ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค.
  • ์ผ๊ด€์„ฑ์„ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ 0์›์ด๋ผ๋Š” ํ• ์ธ ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•  ์ฑ…์ž„์„ ๊ทธ๋Œ€๋กœ DiscountPolicy ๊ณ„์ธต์— ์œ ์ง€์‹œํ‚ค๋Š” ๊ฒƒ์ด๋‹ค. NoneDiscountPolicy ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
public class NoneDiscountPolicy extends DiscountPolicy {

@Override
protected Money getDiscountAmount(Screening screening) {
return Money.ZERO;
}
}
  • ๋‹ค์Œ๊ณผ ๊ฐ™์ด NoneDiscountPolicy์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•ด์„œ ํ• ์ธ๋˜์ง€ ์•Š์€ ์˜ํ™”๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
Movie starWars = new Movie("์Šคํƒ€์›Œ์ฆˆ",
Duration.ofMinutes(210),
Money.wons(10000),
new NoneDiscountPolicy()
);
  • ์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ ๊ธฐ์กด์˜ Movie์™€ DiscountPolicy๋Š” ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  NoneDiscountPolicy๋ผ๋Š” ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ–ˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ์ถ”์ƒํ™”๊ฐ€ ์œ ์—ฐํ•œ ์„ค๊ณ„๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ์ด์œ ๋Š” ์„ค๊ณ„๊ฐ€ ๊ตฌ์ฒด์ ์ธ ์ƒํ™ฉ์— ๊ฒฐํ•ฉ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ๊ฒฐ๋ก ์€ ์œ ์—ฐ์„ฑ์ด ํ•„์š”ํ•œ ๊ณณ์— ์ถ”์ƒํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.

๐ŸŽˆ ์ถ”์ƒ ํด๋ž˜์Šค์™€ ์ธํ„ฐํŽ˜์ด์Šค ํŠธ๋ ˆ์ด๋“œ์˜คํ”„โ€‹

  • NoneDiscountPolicy ํด๋ž˜์Šค์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด getDiscountAmount ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ค ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋”๋ผ๋„ ์ƒ๊ด€์ด ์—†๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ ์ˆ˜ ์žˆ๋Š”๋ฐ ๋ถ€๋ชจ ํด๋ž˜์Šค์ธ DiscountPolicy์—์„œ ํ• ์ธ ์กฐ๊ฑด์ด ์—†์„ ๊ฒฝ์šฐ์— getDiscountAmount๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  • ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ DiscountPolicy๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ”๊พธ๊ณ  NoneDiscountPolicy๊ฐ€ DiscountPolicy์˜ getDiscountAmount ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ calculateDiscountAmount ์˜คํผ๋ ˆ์ด์…˜์„ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • DiscountPolicy ํด๋ž˜์Šค๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
public interface DiscountPolicy {
Money calculateDiscountAmount(Screening screening);
}
  • ์›๋ž˜์˜ DiscountPolicy ํด๋ž˜์Šค์˜ ์ด๋ฆ„์„ DefaultDiscountPolicy๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ์ˆ˜์ •ํ•œ๋‹ค.
public abstract class DefaultDiscountPolicy implements DiscountPolicy {
// ...
}
  • ์ด์ œ NoneDiscountPolicy๊ฐ€ DiscountPolicy ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋ฉด ๊ฐœ๋…์ ์ธ ํ˜ผ๋ž€๊ณผ ๊ฒฐํ•ฉ์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋‹ค.
public class NoneDiscountPolicy implements DiscountPolicy {

@Override
public Money calculateDiscountAmount(Screening screening) {
return Money.ZERO;
}
}
  • ๊ตฌํ˜„๊ณผ ๊ด€๋ จ๋œ ๋ชจ๋“  ๊ฒƒ๋“ค์ด ํŠธ๋ ˆ์ด๋“œ์˜คํ”„์˜ ๋Œ€์ƒ์ด ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด๋‹ค. ์ž‘์„ฑํ•˜๋Š” ๋ชจ๋“  ์ฝ”๋“œ์—๋Š” ํ•ฉ๋‹นํ•œ ์ด์œ ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์‚ฌ์†Œํ•œ ๊ฒฐ์ •์ด๋ผ๋„ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ํ†ตํ•ด ์–ป์–ด์ง„ ๊ฒฐ๋ก ๊ณผ ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฐ๋กผ ์‚ฌ์ด์˜ ์ฐจ์ด๋Š” ํฌ๋‹ค.

๐ŸŽˆ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉโ€‹

  • ์ƒ์†์€ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•์ด๋‚˜ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ์•„๋‹ˆ๋‹ค.
  • ์ƒ์†๋ณด๋‹ค๋Š” ํ•ฉ์„ฑ์ด ๋” ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค. ํ•ฉ์„ฑ์€ ๋‹ค๋ฅธ ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ž์‹ ์˜ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋กœ ํฌํ•จํ•ด์„œ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋งํ•œ๋‹ค.
  • Movie๊ฐ€ DiscountPolicy์˜ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•ฉ์„ฑ์ด๋‹ค.

๐ŸŽˆ ์ƒ์†โ€‹

  • ์ƒ์†์€ ๋‘ ๊ฐ€์ง€ ๊ด€์ ์—์„œ ์„ค๊ณ„์— ์•ˆ ์ข‹์€ ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.
  • ํ•˜๋‚˜๋Š” ์ƒ์†์ด ์บก์Šํ™”๋ฅผ ์œ„๋ฐ˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์„ค๊ณ„๋ฅผ ์œ ์—ฐํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ์ƒ์†์„ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ์ž˜ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์ด ์ž์‹ ํด๋ž˜์Šค์—๊ฒŒ ๋…ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์บก์Šํ™”๊ฐ€ ์•ฝํ™”๋œ๋‹ค. ์บก์Šํ™”์˜ ์•ฝํ™”๋Š” ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜๋„๋ก ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ๋ณ€๊ฒฝํ•  ๋•Œ ์ž์‹ ํด๋ž˜์Šค๋„ ํ•จ๊ป˜ ๋ณ€๊ฒฝ๋  ํ™•๋ฅ ์„ ๋†’์ธ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ์ƒ์†์„ ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ๋Š” ๋ณ€๊ฒฝํ•˜๊ธฐ๋„ ์–ด๋ ค์›Œ์ง„๋‹ค.
  • ๋‘ ๋ฒˆ์งธ ๋‹จ์ ์€ ์„ค๊ณ„๊ฐ€ ์œ ์—ฐํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ƒ์†์€ ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ์ž์‹ ํด๋ž˜์Šค ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ์ปดํŒŒ์ผ ์‹œ์ ์— ๊ฒฐ์ •ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์‹คํ–‰ ์‹œ์ ์— ๊ฐ์ฒด์˜ ์ข…๋ฅ˜๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์˜ˆ๋ฅผ ๋“ค์–ด ์‹คํ–‰ ์‹œ์ ์— ๊ธˆ์•ก ํ• ์ธ ์ •์ฑ…์ธ ์˜ํ™”๋ฅผ ๋น„์œจ ํ• ์ธ ์ •์ฑ…์œผ๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด, ์ƒ์†์„ ์‚ฌ์šฉํ•œ ์„ค๊ณ„์—์„œ๋Š” AmountDiscountPolicy์˜ ์ธ์Šคํ„ด์Šค๋ฅผ PercentDiscountPolicy์˜ ์ธ์Šคํ„ด์Šค๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์€ ๋ถ€๋ชจ ํด๋ž˜์Šค์™€ ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋ผ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๋‹ค.
  • ๋ฐ˜๋ฉด ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋กœ ์—ฐ๊ฒฐํ•œ ๊ธฐ์กด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์‹คํ–‰ ์‹œ์ ์— ํ• ์ธ ์ •์ฑ…์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.
public class Movie {
private DiscountPolicy discountPolicy;

public void changeDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
  • ๊ธˆ์•ก ํ• ์ธ ์ •์ฑ…์ด ์ ์šฉ๋œ ์˜ํ™”์— ๋น„์œจ ํ• ์ธ ์ •์ฑ…์ด ์ ์šฉ๋˜๋„๋ก ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์€ ์ƒˆ๋กœ์šด DiscountPolicy ์ธ์Šคํ„ด์Šค๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์ž‘์—…์œผ๋กœ ๋ฐ”๋€๋‹ค.
Movie avatar = new Movie("์•„๋ฐ”ํƒ€",
Duration.ofMinutes(120),
Money.wons(10000),
new AmountDiscountPolicy(Money.wons(800), ...)
);

avatar.changeDiscountPolicy(new PercentDiscountPolicy(0.1, ...));

๐ŸŽˆ ํ•ฉ์„ฑโ€‹

  • Movie๋Š” ์š”๊ธˆ์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด DiscountPolicy์˜ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•œ๋‹ค. ์ด ๋ฐฉ๋ฒ•์ด ์ƒ์†๊ณผ ๋‹ค๋ฅธ ์ ์€ Movie๊ฐ€ DiscountPolicy์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ์•ฝํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ๋‹ค.
  • ์ด์ฒ˜๋Ÿผ ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ๋ฉ”์‹œ์ง€๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•ฉ์„ฑ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„์„ ํšจ๊ณผ์ ์œผ๋กœ ์บก์Šํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ์˜์กดํ•˜๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๊ต์ฒดํ•˜๋Š” ๊ฒƒ์ด ๋น„๊ต์  ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ์„ค๊ณ„๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค.
  • ์ƒ์†์€ ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜๋Š” ๋ฐ ๋น„ํ•ด ํ•ฉ์„ฑ์€ ๋ฉ”์‹œ์ง€๋ฅผ ํ†ตํ•ด ๋Š์Šจํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•ด์„œ ์ƒ์†๋ณด๋‹ค๋Š” ํ•ฉ์„ฑ์„ ์„ ํ˜ธํ•œ๋‹ค.
  • ๊ทธ๋ ‡๋‹ค๊ณ  ํ•ด์„œ ์ƒ์†์„ ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜์ง€ ๋ง๋ผ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ณ  DiscountPolicy์™€ AmountDiscountPolicy, PercentDiscountPolicy๋Š” ์ƒ์† ๊ด€๊ณ„๋กœ ์—ฐ๊ฒฐ๋ผ ์žˆ๋Š”๋ฐ ์ด์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ƒ์†๋ณด๋‹ค ํ•ฉ์„ฑ์„ ์„ ํ˜ธ๋‚˜๋Š” ๊ฒƒ์ด ์˜ณ์ง€๋งŒ ๋‹คํ˜•์„ฑ์„ ์œ„ํ•ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ƒ์†๊ณผ ํ•ฉ์„ฑ์„ ํ•จ๊ป˜ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜๋ฐ–์— ์—†๋‹ค.
  • ๊ฐ์ฒด์ง€ํ–ฅ์˜ ์„ค๊ณ„์˜ ํ•ต์‹ฌ์€ ์ ์ ˆํ•œ ํ˜‘๋ ฅ์„ ์‹๋ณ„ํ•˜๊ณ  ํ˜‘๋ ฅ์— ํ•„์š”ํ•œ ์—ญํ• ์„ ์ •์˜ํ•œ ํ›„์— ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ ์ ˆํ•œ ๊ฐ์ฒด์—๊ฒŒ ์ ์ ˆํ•œ ์ฑ…์ž„์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด๋‹ค.