๐ 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
๋ ์์ ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋ผ ์๋๋ฐ ์ด์ฒ๋ผ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ์์๋ณด๋ค ํฉ์ฑ์ ์ ํธ๋๋ ๊ฒ์ด ์ณ์ง๋ง ๋คํ์ฑ์ ์ํด ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ์์๊ณผ ํฉ์ฑ์ ํจ๊ป ์กฐํฉํด์ ์ฌ์ฉํ ์๋ฐ์ ์๋ค. - ๊ฐ์ฒด์งํฅ์ ์ค๊ณ์ ํต์ฌ์ ์ ์ ํ ํ๋ ฅ์ ์๋ณํ๊ณ ํ๋ ฅ์ ํ์ํ ์ญํ ์ ์ ์ํ ํ์ ์ญํ ์ ์ํํ ์ ์๋ ์ ์ ํ ๊ฐ์ฒด์๊ฒ ์ ์ ํ ์ฑ ์์ ํ ๋นํ๋ ๊ฒ์ด๋ค.