
์ง์ ํ ๊ฐ์ฒด์งํฅ ํจ๋ฌ๋ค์์ผ๋ก์ ์ ํ์ ํด๋์ค๊ฐ ์๋ ๊ฐ์ฒด์ ์ด์ ์ ๋ง์ถ ๋์๋ง ์ป์ ์ ์๋ค.
์ด๋ฅผ ์ํด์๋ ํ๋ก๊ทธ๋๋ฐํ๋ ๋์ ๋ค์์ ๋ ๊ฐ์ง์ ์ง์คํด์ผ ํ๋ค.
๋๋ฉ์ธ(domain)
๊ฐ์ฒด์งํฅ ํจ๋ฌ๋ค์์ด ๊ฐ๋ ฅํ ์ด์

์ผ๋ฐ์ ์ผ๋ก ํด๋์ค ๊ธฐ๋ฐ์ ๊ฐ์ฒด์งํฅ ์ธ์ด์์๋ ๋๋ฉ์ธ ๊ฐ๋
์ ๊ตฌํํ๊ธฐ ์ํด Class๋ฅผ ์ฌ์ฉํ๋ค.
Class์ ์ด๋ฆ์ ๋์๋๋ ๋๋ฉ์ธ ๊ฐ๋
์ ์ด๋ฆ๊ณผ ๋์ผํ๊ฒ ํ๊ฑฐ๋ ์ ์ด๋ ์ ์ฌํด์ผ ํ๋ค.
Class ์ฌ์ด์ ๊ด๊ณ๋ ์ต๋ํ ๋๋ฉ์ธ ๊ฐ๋
์ฌ์ด์ ๋งบ์ด์ง ๊ด๊ณ์ ์ ์ฌํ๊ฒ ๋ง๋ค์ด์ผ ํ๋ก๊ทธ๋จ์ ๊ตฌ์กฐ๋ฅผ ์ดํดํ๊ณ , ์์ํ๊ธฐ ์ฌ์์ง๋ค.
๋ฐ๋ผ์ Class ๋ค์ด์ด๊ทธ๋จ์ ๋๋ฉ์ธ ๋ชจ๋ธ๊ณผ ์ ์ฌํ ํํ๋ฅผ ๋ณด์ด๊ฒ ๋๋ค. ๋ค์ ์ฌ์ง๊ณผ ๊ฐ์ด ๋ง์ด๋ค.

๊ฐ์ฒด์ 2๊ฐ์ง ์ค์ํ ์ฌ์ค
๊ฐ์ฒด์งํฅ ํจ๋ฌ๋ค์์์๋ ๊ฐ์ฒด๋ผ๋ ๋จ์ ์์ ๋ฐ์ดํฐ์ ๊ธฐ๋ฅ์ ํ ๋ฉ์ด๋ฆฌ๋ก ๋ฌถ์์ผ๋ก์จ ์บก์ํ ์ํฌ ์ ์๋ค. ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ค์ ์ํ์ ํ๋์ ์บก์ํํ๋ ๊ฒ์์ ํ ๊ฑธ์ ๋ ๋์๊ฐ ์ธ๋ถ์์์ ์ ๊ทผ์ ํต์ ํ ์ ์๋ ์ ๊ทผ ์ ์ด(access control) ๋ฉ์ปค๋์ฆ๋ ํจ๊ป ์ ๊ณตํ๋ค.
๊ฐ์ฒด์งํฅ ์ธ์ด์์๋ public, protected, private ์ ๊ฐ์ ์ ๊ทผ ์์ ์๋ฅผ ์ ๊ณตํ๋ค.
์ ๊ฐ์ฒด ๋ด๋ถ์ ๋ํ ์ ๊ทผ์ ํต์ ํ ๊น?
๋ฐ๋ก ๊ฐ์ฒด๋ฅผ ์์จ์ ์ธ ์กด์ฌ๋ก ๋ง๋ค๊ธฐ ์ํด์๋ค. ๊ฐ์ฒด์งํฅ์ ํต์ฌ์ ์ค์ค๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ , ํ๋จํ๊ณ , ํ๋ํ๋ ์์จ์ ์ธ ๊ฐ์ฒด๋ค์ ๊ณต๋์ฒด๋ฅผ ๊ตฌ์ฑํ๋ ๊ฒ์ด๋ค. ๊ฐ์ฒด๊ฐ ์์จ์ ์ธ ์กด์ฌ๋ก ์๊ธฐ ์ํด์๋ ์ธ๋ถ์ ๊ฐ์ญ์ ์ต์ํํด์ผ ํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด ๋ด๋ถ์ ๋ํ ์ ๊ทผ์ ํต์ ํ๋ค.
์ธ๋ถ์์ ๊ฐ์ฒด์ ๊ฒฐ์ ์ ์ง์ ์ ์ผ๋ก ๊ฐ์ ํด์๋ ์๋๋ค. ๊ฐ์ฒด์๊ฒ ์์ฒญ๋ง ํ๊ณ , ์ค์ค๋ก ์ต์ ์ ๋ฐฉ๋ฒ์ ๊ฒฝ์ฒญํ๋๋ก ํด์ผํ๋ค.
์บก์ํ์ ์ ๊ทผ ์ ์ด๋ ๊ฐ์ฒด๋ฅผ ๋ ๋ถ๋ถ์ผ๋ก ๋๋๋ค.
์ผ๋ฐ์ ์ผ๋ก Java์ ๊ฒฝ์ฐ ํด๋์ค์ ์ธ์คํด์ค ๋ณ์์ ๊ฐ์์ฑ์ private์ด๊ณ , ์ธ๋ถ์ ์ ๊ณตํด์ผ ํ ๋ฉ์๋๋ public์ด๋ค.
public interface์๋ public์ผ๋ก ์ง์ ๋ ๋ฉ์๋๋ง ํฌํจ๋๋ค.
๊ทธ ์ธ์ private ๋ฉ์๋, ์ธ์คํด์ค ๋ณ์๋ implementation์ ํด๋นํ๋ค.
Screening(์์), Money(๊ธ์ก), Movie(์ํ), Reservation(์์ฝ) ํด๋์ค๋ฅผ ๋ณด์ฌ์ค ๊ฒ์ด๋ค. ์ด๋ ์ฝ๋๋ฅผ ๋ณผ ๋ ์ํ ์๋งค๋ผ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํ ๊ฐ์ฒด๋ค ์ฌ์ด์ ์ด๋ค์ง๋ ์ํธ์์ฉ์ ์ ์ํด์ ์ง์ผ๋ณด์.
Screening(์์)
public class Screening {
private Movie movie;
public Reservation reserve(Customer customer, int audienceCount) {
return new Reservation(customer, this, calculateFee(audienceCount),
audienceCount);
}
private Money calculateFee(int audienceCount) {
return movie.calculateMovieFee(this).times(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));
}
public static Money wons(double amount) {
return new Money(BigDecimal.valueOf(amount));
}
Money(BigDecimal amount) {
this.amount = amount;
}
public Money plus(Money amount) {
return new Money(this.amount.add(amount.amount));
}
public Money minus(Money amount) {
return new Money(this.amount.subtract(amount.amount));
}
public Money times(double percent) {
return new Money(this.amount.multiply(BigDecimal.valueOf(percent)));
}
public boolean isLessThan(Money other) {
return amount.compareTo(other.amount) < 0;
}
public boolean isGreaterThanOrEqual(Money other) {
return amount.compareTo(other.amount) >= 0;
}
}
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;
}
}
์ํ ์๋งค๋ผ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํ ๊ฐ์ฒด๋ค ์ฌ์ด์ ์ด๋ค์ง๋ ์ํธ์์ฉ์ ๋ณด์๋๊ฐ?
์ด๊ฒ์ ํ๋ ฅ(Collaboration) ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋จ์ ์์ฑํ ๋๋ ๋จผ์ ํ๋ ฅ์ ๊ด์ ์์ ์ด๋ค ๊ฐ์ฒด๊ฐ ํ์ํ์ง๋ฅผ ๊ฒฐ์ ํ๊ณ , ๊ฐ์ฒด๋ค์ ๊ณตํต ์ํ์ ํ์๋ฅผ ๊ตฌํํ๊ธฐ ์ํด ํด๋์ค๋ฅผ ์์ฑํ๋ค.
๊ฐ์ฒด๋ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ธํฐํ์ด์ค์ ๊ณต๊ฐ๋ ํ๋์ ์ํํ๋๋ก ์์ฒญ(request) ํ ์ ์๋ค. ์์ฒญ์ ๋ฐ์ ๊ฐ์ฒด๋ ์์จ์ ์ธ ๋ฐฉ๋ฒ์ ๋ฐ๋ผ ์์ฒญ์ ์ฒ๋ฆฌํ ํ ์๋ต(response)ํ๋ค.
๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ํธ์์ฉํ๋ ์ ์ผํ ๋ฐฉ๋ฒ์ ๋ฉ์์ง๋ฅผ ์ ์ก(send a message)ํ๋ ๊ฒ ๋ฟ์ด๋ค.
๋ฉ์์ง๋ฅผ ์์ ํ ๊ฐ์ฒด๋ ์ค์ค๋ก์ ๊ฒฐ์ ์ ๋ฐ๋ผ ์์จ์ ์ผ๋ก ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ๋ค.
์ด์ฒ๋ผ ์์ ๋ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์์ ๋ง์ ๋ฐฉ๋ฒ์ ๋ฉ์๋(method)๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์์์ ์๊ฐํ๋ ์ฝ๋์ ์ผ๋ถ๋ถ์ ๋ค์ ๋ณด์.
public class Screening {
private Money calculateFee(int audienceCount) {
return movie.calculateMovieFee(this).times(audienceCount);
}
}
์ด ์ฝ๋์ calculateFee ๋ฉ์๋๋ฅผ ์ค๋ช ํ ๋ ์ด๋ป๊ฒ ๋งํ ๊ฒ์ธ๊ฐ?
์ ๋ต์ 2๋ฒ์ด๋ค.
์ฌ์ค Screening์ Movie ์์ calculateMovieFee ๋ฉ์๋๊ฐ ์กด์ฌํ๊ณ ์๋์ง ์ ์ ์๋ค.
๋จ์ง, Movie๊ฐ calculateMovieFee ๋ฉ์์ง์ ์๋ตํ ์ ์๋ค๊ณ ๋ฏฟ๊ณ ๋ฉ์์ง๋ฅผ ์ ์กํ ๋ฟ์ด๋ค.
๋ฉ์์ง๋ฅผ ๋ฐ์ Movie๋ ์ค์ค๋ก ์ ์ ํ ๋ฉ์๋๋ฅผ ์ ํํ๋ค.
Movie
public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {
this.title = title;
this.runningTime = runningTime;
this.fee = fee;
this.discountPolicy = discountPolicy;
}
Movie์ ์์ฑ์๋ฅผ ์ ์ดํด๋ณด์.
๋ถ๋ช
ํ ์ธ ์ ๋ต์ ๋ฐ๊ณ ์๊ธด ํ์ง๋ง, ์ด๋ ํ ํ ์ธ ์ ๋ต์ ์ฌ์ฉํ ์ง ๋ช
์๊ฐ ๋์ด์์ง ์๋ค.
์ด ์ฝ๋์๋ ๊ฐ์ฒด์งํฅ์์ ์ค์ํ ๊ฐ๋
๋๊ฐ์ง๊ฐ ์จ๊ฒจ์ ธ์๋๋ฐ,
ํ๋๋ ์์, ํ๋๋ ๋คํ์ฑ์ด๋ค. ๊ทธ ๊ธฐ๋ฐ์๋ ์ถ์ํ์ ์๋ฆฌ๊ฐ ์จ๊ฒจ์ ธ ์๋ค.
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);
}
์์ ํด๋์ค์ธ DiscountPolicy ์์ ์ค๋ณต ์ฝ๋๋ฅผ ๋๊ณ , AmountPolicy, PercentDiscountPolicy๊ฐ ์ด ํด๋์ค๋ฅผ ์์ํ๋ค.
์ค์ ์ ํ๋ฆฌ์ผ์ด์
์์ DiscountPolicy์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ abstract class(์ถ์ ํด๋์ค)๋ก ๊ตฌํํ๋ค.
DiscountPolicy๋ ํ ์ธ ์ฌ๋ถ์ ์๊ธ ๊ณ์ฐ์ ํ์ํ ์ ์ฒด์ ์ธ ํ๋ฆ์ ์ ์ํ์ง๋ง, ์ค์ง์ ์ธ ์๊ธ์ ๊ณ์ฐํ๋ ๋ถ๋ถ์ ์ถ์๋ฉ์๋์ธ getDiscountAmount() ๋ฉ์๋์ ์์ํ๋ค.
์ด์ฒ๋ผ ๊ธฐ๋ณธ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ ํ๋ฆ์ ๊ฒฐ์ ํ๊ณ , ์ค๊ฐ์ ํ์ํ ์ฒ๋ฆฌ๋ฅผ ํ์ ํด๋์ค์๊ฒ ์์ํ๋ ๋์์ธ ํจํด์ TEMPLATE METHOD ํจํด ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ด ์ด ํจํด์ ๋ง์ด ์ฌ์ฉํ๋ค.
Movie
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));
}
}
Movieํด๋์ค ์ด๋์๋ ํ ์ธ ์ ์ฑ
์ด ์ ์ก์ ์ธ์ง ์ ๋ฅ ์ ์ธ์ง ์ ์๋์ด ์์ง ์๋ค.
๊ทธ๋ฐ๋ฐ, ์ด๋ป๊ฒ ์๊ธ ๊ณ์ฐ์ ํ ์ธ ์ ์ฑ
์ ์ ํ ์ ์์๊น?
์ด๋ฅผ ์๊ธฐ ์ํด์๋ ์์๊ณผ ๋คํ์ฑ์ ์์์ผํ๋ค.

์์ ๊ทธ๋ฆผ์ Movie์ DiscountPolicy ๊ณ์ธต ์ฌ์ด์ ๊ด๊ณ๋ฅผ ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ผ๋ก ํํํ ๊ฒ์ด๋ค.
Movie๋ DiscountPolicy์ ์ฐ๊ฒฐ๋์ด ์์ผ๋ฉฐ, AmountDiscountPolicy์ PercentDiscountPolicy๋ ์ถ์ ํด๋์ค์ธ DiscountPolicy๋ฅผ ์์๋ฐ๋๋ค.
์ฌ๊ธฐ์ ์์ธํ ๋ด์ผ ํ ๋ถ๋ถ์ Movie ํด๋์ค๊ฐ AmountDiscountPolicy, PercentDiscountPolicy์ ๊ฐ์ ์ธ์คํด์ค์ ์์กดํ๋ ๊ฒ์ด ์๋ ์ถ์ ํด๋์ค์ ์์กดํ๊ณ ์๋ค๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด Movie์ ์ธ์คํด์ค๊ฐ ์ฝ๋ ์์ฑ ์์ ์๋ ์กด์ฌ์กฐ์ฐจ ๋ชจ๋ฅด๋ AmountDiscountPolicy, PercentDiscountPolicy์ ์ธ์คํด์ค์ ์คํ ์์ ์ ํ๋ ฅ ๊ฐ๋ฅํ ์ด์ ๋ ๋ฌด์์ผ๊น?
Movie์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ์ฝ๋๋ฅผ ์ดํด๋ณด์
Movie avartar = new Movie("์๋ฐํ",
Duration.ofMinutes(120),
Money.wons(10000),
new PercentDisCountPolicy(0,1,....));
์ฝ๋์์์ Movie๋ DiscountPolicy ์ธ์คํด์ค๋ฅผ ์์กดํ๋ค. ๊ทธ๋ฌ๋ ์์ฑ์์ ์ PercentDiscountPolicy ์ธ์คํด์ค๋ฅผ ์ ๋ฌํ๋ฉด ํด๋น ์ธ์คํด์ค๋ก ์์ฑํ ์ ์๋ค.

์ฝ๋ ์์์ Movie๋ DiscountPolicy์ ์์กดํ๋ค. ๊ทธ๋ฌ๋ ์คํ ์์ ์๋ Movie์ ์ธ์คํด์ค๋ DiscountPolicy๋ฅผ ์์ํ ํ์ ํด๋์ค์ ์ธ์คํด์ค์ ์์กดํ๋ค.
ํต์ฌ์ ์ฝ๋์ ์์กด์ฑ๊ณผ ์คํ ์์ ์ ์์กด์ฑ์ด ์๋ก ๋ค๋ฅผ ์ ์๋ค๋ ์ ์ด๋ค.
๊ฐ๊ณผํ์ง๋ง์
์ ์ฐํ๊ฒ ์๋ฌด๋ฆฌ ์ข๋ค์ง๋ง, ์คํ, ์ปดํ์ผ ์์ ์ ์์กด์ฑ์ด ๋ค๋ฅผ ์๋ก ์ฝ๋๋ ์ ์ฐํด์ง๋ค.
ํ์ง๋ง, ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ ์ด๋ ค์์ง๋ค. ํ์ฌ Movie ์ธ์คํด์ค๊ฐ ์ด๋ค ์์กด์ฑ์ ๊ฐ์ง๊ณ ์๋์ง ์คํ์์ ๋ง๋ค ๋ณ๊ฒฝ๋ ์ ์๊ธฐ๋๋ฌธ์
๋๋ฒ๊น ํ๊ธฐ๊ฐ ์ด๋ ค์์ง ์ ์๋ค. ์ด์ฒ๋ผ ๋ฌด์กฐ๊ฑด ์ ์ฐํ ์ค๊ณ๋, ์ฝ๊ธฐ ์ฌ์ด ์ฝ๋๋ ์ ๋ต์ด ์๋๋ค.
์์์ด ๊ฐ์น ์๋ ์ด์ ๋ ๋ถ๋ชจ ํด๋์ค๊ฐ ์ ๊ณตํ๋ ๋ชจ๋ ์ธํฐํ์ด์ค๋ฅผ ์์ ํด๋์ค๊ฐ ๋ฌผ๋ ค๋ฐ์ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
(๋จ์ํ ๋ฉ์๋๋ ์ธ์คํด์ค ๋ณ์๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒ์ด ์๋)
์์์ ๊ทธ์ ๋ถ๋ชจ ํด๋์ค์ ๊ฒ์ ๋ฌผ๋ ค๋ฐ๋ ๊ฒ์ด ์๋๋ค.
์์์ ํต์ฌ์ ํ์ฅ(extends)์ ์๋ค.
Movie์ calculateMovieFee ๋ฉ์๋์ ๊ฐ์ด discountPolicy.calculateDiscountamount ๋ฉ์๋๋ฅผ ํธ์ถ ํ ๋, DiscountPolicy๋ฅผ ์์๋ฐ์ ์ธ์คํด์ค๋ค์ด ์ด ์ธํฐํ์ด์ค๋ฅผ ์๊ณ ์๊ธฐ ๋๋ฌธ์, ํด๋น ์ธ์คํด์ค๋ค์ด ๋ค์ด์๋ ๋ฉ์์ง๋ฅผ ์ก์์ ํ ์ ์๋ ๊ฒ์ด๋ค.
์ปดํ์ผ๋ฌ๋ ์ฝ๋์์์ ๋ถ๋ชจ ํด๋์ค๊ฐ ๋์ค๋ ๋ชจ๋ ์ฅ์์์ ์์ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ฉํ๋ค.
์ด์ฒ๋ผ ์์ ํด๋์ค๊ฐ ๋ถ๋ชจํด๋์ค๋ฅผ ๋์ ํ๋ ๊ฒ์ ์ ์บ์คํ ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
Movie ์ ์ฅ์์๋ ์์ ๊ณผ ํ๋ ฅํ๋ ๊ฐ์ฒด๊ฐ ์ด๋ค ํด๋์ค์ ์ธ์คํด์ค์ธ์ง๊ฐ ์ค์ํ ๊ฒ์ด ์๋๋ผ, calculateDiscountAmount๋ผ๋ ๋ฉ์์ง๋ฅผ ์์ ํ ์ ์๋ค๋ ์ฌ์ค์ด ์ค์ํ๋ค.
๋ฉ์์ง์ ๋ฉ์๋์ ์ฐจ์ด๋ฅผ ์์.
Movie๋ DiscountPolicy์ ์ธ์คํด์ค์๊ฒ calculateDiscountAmount ๋ฉ์์ง๋ฅผ ์ ์กํ๋ค.
์ดํ ์ฐ๊ฒฐ๋ ์ธ์คํด์ค๊ฐ ์ค๋ฒ๋ผ์ด๋ฉ๋ ๋ฉ์๋๋ฅผ ์คํํ๋ค.
Movie๊ฐ ๋์ผํ ๋ฉ์์ง๋ฅผ ์ ์กํ์ง๋ง, ์ค์ ๋ก ์ด๋ค ๋ฉ์๋๊ฐ ์คํ๋ ๊ฒ์ธ์ง๋ ๋ฉ์์ง๋ฅผ ์์ ํ๋ ๊ฐ์ฒด ํด๋์ค๊ฐ ๋ฌด์์ด๋์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋๋ฐ, ์ด๋ฅผ ๋คํ์ฑ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฉ์์ง์ ๋ฉ์๋๋ฅผ ์คํ ์์ ์ ๋ฐ์ธ๋ฉ ํ๋ ๊ฒ์ ์ง์ฐ ๋ฐ์ธ๋ฉ(lazy binding), ๋์ ๋ฐ์ธ๋ฉ(dynamic binding)์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๊ทธ์ ๋ฐํด ์ ํต์ ์ธ ํจ์ ํธ์ถ์ฒ๋ผ ์ปดํ์ผ ์์ ์ ์คํ๋ ํจ์๋ ํ๋ก์์ ธ๋ฅผ ๊ฒฐ์ ํ๋ ๊ฒ์ ์ด๊ธฐ ๋ฐ์ธ๋ฉ, ์ ์ ๋ฐ์ธ๋ฉ์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
ํ๋์ ๋ฉ์์ง๋ฅผ ์ ํ์ ์ผ๋ก ์๋ก ๋ค๋ฅธ ๋ฉ์๋์ ์ฐ๊ฒฐ ํ ์ ์๋ ๊ฒ์ ์ง์ฐ๋ฐ์ธ๋ฉ์ด๋ผ๋ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.

์ ๊ทธ๋ฆผ์ ์ถ์ํ๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ 2๊ฐ์ง ์ฅ์ ์ ๋ณด์ฌ์ค๋ค.
์ ๋ค์ด์ด๊ทธ๋จ์ ํ๋์ ๋ฌธ์ฅ์ผ๋ก ์ ๋ฆฌํ๋ฉด
"์ํ ์๋งค ์๊ธ์ ์ต๋ ํ๋์ ํ ์ธ ์ ์ฑ
๊ณผ ๋ค์์ ํ ์ธ ์กฐ๊ฑด์ ์ด์ฉํด ๊ณ์ฐํ ์ ์๋ค."์ ๊ฐ๋ค.
์ ๋ฌธ์ฅ์ "๊ธ์ก ํ ์ธ ์ ์ฑ
๊ณผ ๋ ๊ฐ์ ์์ ์กฐ๊ฑด, ํ ๊ฐ์ ๊ธฐ๊ฐ ์กฐ๊ฑด์ ์ด์ฉํด ๊ณ์ฐํ ์ ์๋ค"๋ผ๋ ๋ฌธ์ฅ์ ํฌ๊ดํ ์ ์๋ค๋ ์ฌ์ค์ด ์ค์ํ๋ค.
์ถ์ํ๋ฅผ ํตํด ์์ ์ ์ฑ
์ ๊ธฐ์ ํ๋ค๋ ๊ฒ์ ๊ธฐ๋ณธ์ ์ธ ์ ํ๋ฆฌ์ผ์ด์
์ ํ๋ ฅ ํ๋ฆ์ ๊ธฐ์ ํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ํ ์๋งค ๊ฐ๊ฒฉ์ ๊ณ์ฐํ๊ธฐ ์ํ ํ๋ฆ์ ํญ์ Movie -> DiscountPolicy -> DiscountCondition ์์๋ก ํ๋ฌ๊ฐ๋ค.
ํ ์ธ ์ ์ฑ
, ์กฐ๊ฑด์ ์์๋ค์ ์ถ์ํ๋ฅผ ์ด์ฉํด์ ์ ์ํ ํ๋ฆ์ ๊ทธ๋๋ก ๋ฐ๋ฅด๊ฒ ๋๋ค.
์ถ์ํ๊ฐ ์ ์ฐํ ์ค๊ณ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ ์ด์ ๋ ์ค๊ณ๊ฐ ๊ตฌ์ฒด์ ์ธ ์ํฉ์ ๊ฒฐํฉ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ๋๋ฌธ์ด๋ค.
Movie๋ ํน์ ํ ํ ์ธ ์ ์ฑ ์ ๋ฌถ์ด์ง ์๋๋ค. ํ ์ธ ์ ์ฑ ์ ๊ตฌํํ ํด๋์ค๊ฐ DiscountPolicy๋ฅผ ์์๋ฐ๊ณ ์๋ค๋ฉด ์ด๋ค ํด๋์ค์๋ ํ๋ ฅ์ด ๊ฐ๋ฅํ๋ค.
DiscountPolicy ์ญ์ ํน์ ํ ์ธ ์กฐ๊ฑด์ ๋ฌถ์ฌ์์ง ์๋ค. DiscountCondition์ ์์๋ฐ์ ์ด๋ค ํด๋์ค์๋ ํ๋ ฅ์ด ๊ฐ๋ฅํ๋ค.
์ด ๋ชจ๋ ๊ฒ์ด ์ถ์ํ ๋๋ถ์ด๋ค.
ํ ์ธ ์ ์ฑ
์ด ์๋ ๊ฒฝ์ฐ๋ ๋ชจ๋ ์ดํด๋ดค๋ค.
๊ทธ๋ฐ๋ฐ ํ ์ธ ์ ์ฑ
์ด ์๋ ๊ฒฝ์ฐ๋ ์ด๋ป๊ฒ ํ ๊น?
์ด๋ฐ ๊ฒฝ์ฐ์, NoneDiscountPolicy๋ผ๋ ๊ฒ์ ์ถ๊ฐํ์ฌ, ํ ์ธ์ ์ฑ ์ ์ฌ์ฉํ์ง ์์ ๊ฒฝ์ฐ , ์ด ์ ์ฑ ์ ์ฌ์ฉํ๋๋ก ํ์.
public class NoneDiscountPolicy extends DiscountPolicy {
@Override
protected Money getDiscountAmount(Screening screening) {
return Money.ZERO;
}
}
์ด ์ ์ฑ ์ ์ฌ์ฉํ๋ฉด Movie ํด๋์ค๋ฅผ ์์ ํ ํ์๋ ์๊ณ , ๊ธฐ๋ฅ์ ๋ฌธ์ ์์ด ์๋ ์ํฌ ์ ์๋ค.
์์์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด ๋๋ฆฌ ์ฌ์ฉ๋๋ ๋ฐฉ๋ฒ์ด๋ค. ๊ทธ๋ฌ๋ ๋๋ฆฌ ์ฌ์ฉ๋๋ ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํด์ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ์๋๋ค. ๊ฐ์ฒด์งํฅ ์ค๊ณ์ ๊ด๋ จ๋ ์๋ฃ๋ฅผ ๋ณธ ์ฌ๋๋ค์ ์ฝ๋ ์ฌ์ฌ์ฉ์ ์ํด์๋ ์์๋ณด๋ค๋ ํฉ์ฑ(composition)์ด ๋ ์ข์ ๋ฐฉ๋ฒ์ด๋ผ๋ ์ด์ผ๊ธฐ๋ฅผ ๋ง์ด ๋ค์์ ๊ฒ์ด๋ค.
ํฉ์ฑ์ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ธ์คํด์ค๋ฅผ ์์ ์ ์ธ์คํด์ค ๋ณ์๋ก ํฌํจํด์ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋งํ๋ค.
๋ค์์ ํฉ์ฑ ๋ฐฉ์์ ์์์ผ๋ก ๋ณ๊ฒฝํ ๋ค์ด์ด๊ทธ๋จ์ด๋ค.

์์๋ก ๋ค์๋ฉด Movie๊ฐ DiscountPolicy ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋๊ฒ์ด ๋ฐ๋ก ํฉ์ฑ์ด๋ค.
๋ง์ฝ์ ์ด๊ฒ์ ์์์ผ๋ก ์ฌ์ฉํ๊ณ ์ํ๋ฉด Movie๋ฅผ ์์๋ฐ๋ AmountdiscountMovie, PercentDiscountMoive๋ฅผ ๋ง๋ค ์ ์๋ค.
์์ ๋์ ํฉ์ฑ์ ์ ํธํ๋ ์ด์ ๋ ๋ฌด์์ผ๊น?
์์์ ๋ ๊ฐ์ง ๊ด์ ์์ ์ค๊ณ์ ์ ์ข์ ์ํฅ์ ๋ฏธ์น๋ค.
Movie๋ ์๊ธ์ ๊ณ์ฐํ๊ธฐ ์ํด DiscountPolicy์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ค.
Movie๊ฐ DiscountPolicy์ ์ธํฐํ์ด์ค๋ฅผ ํตํด ์ฝํ๊ฒ ๊ฒฐํฉ๋๋์ ์ ์ด์ฉํ๋ ๊ฒ์ด๋ค.
Movie๋ DiscountPolicy์ calculateDiscountAmount ๋ฉ์์ง๋ฅผ ํตํด ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ค.
์ด๊ฒ์ ํฉ์ฑ์ด๋ผ๊ณ ํ๋ค.
ํฉ์ฑ์ ์์์ด ๊ฐ์ง๋ ๋ ๊ฐ์ง ๋ฌธ์ ์ ์ ๋ชจ๋ ํด๊ฒฐํ๋ค.
ํฉ์ฑ์ ์ธํฐํ์ด์ค์ ์ ์๋ ๋ฉ์์ง๋ฅผ ํตํด์๋ง ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์บก์ํ๊ฐ ๊ฐ๋ฅํ๋ฉฐ, ์์กดํ๋ ์ธ์คํด์ค๊ฐ ์ฝ๊ฒ ๊ต์ฒด ๋ ์ ์๊ธฐ ๋๋ฌธ์ ์ค๊ณ๊ฐ ์ ์ฐํด์ง๋ค.
์์์ ๋ฌด์กฐ๊ฑด ์ฌ์ฉํ์ง ๋ง๋ผ๋ ๊ฒ์ ์๋๋ค. ๋๋ถ๋ถ์ ์ค๊ณ์์๋ ์์๊ณผ ํฉ์ฑ์ ์ ์ ํ ์์ด ์ฌ์ฉํด์ผํ๋ค.
Movie์ DiscountPolicy๋ ํฉ์ฑ์ผ๋ก ์ฐ๊ฒฐ๋์ด์์ง๋ง DiscountPolicy, AmountDiscountPolicy, PercentDiscountPolicy๋ ์์๊ด๊ณ๋ก ๋์ด์๋ค. ์ด์ฒ๋ผ ์ค๋ณต ๊ตฌํ๋ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด์ ์์๋ ์ ์ ํ ์์ด์ ์ฌ์ฉํ ์ ์๋ค.
๋ง์ ์ฑ ๋ค๊ณผ ๊ธ์์ ์์์ ๋๋๋ก ํผํ๋ผ๊ณ ๋งํ๋ค. ์ด๋๋ฌธ์ ์์์ ์ต๋ํ ๊ธฐํผํ๊ณ ๊ตฌํ, ํฉ์ฑ์ ํ์ฉํด์ผํ๋ค๋ ์๊ฐ์ ์ฌ๋ก์กํ์์๋๋ฐ ์ด๋ฒ ๊ธฐํ์ ์๊ฐ์ ์ ์ ํ ์ ์๊ฒ ๋์๋ค.
๋น์ทํ๋ค๊ณ ์๊ฐํ๋ ๋ฉ์๋์ ๋ฉ์์ง์ ์ฐจ์ด ๋ํ ๋๊ฒ ์๊ฐํ๊ฒ ๋์๋ค.
๋ฉ์๋๋ ์ฝ๋์ ์์จ์ฑ์ ๋์ฌ์ฃผ๊ณ ๋ฉ์์ง๋ ๊ฐ์ฒด๋ค๊ฐ์ ํ๋ ฅ์ ์ํ ์๋จ์ด๋ผ๊ณ ์๊ฐํ๊ฒ ๋์๋ค.
์ฃผ๋ก DB์ ์์กดํ๊ณ , DB ์ค์ฌ์ ์ผ๋ก ์๊ฐํ๋๊ฑฐ ๊ฐ์๋ฐ ์ ์ ์ด๋ฐ ์๊ฐ์์ ํํผํ๊ณ ์๋ค.
๊ฐ์ฅ ํฌ๊ฒ ๋๋์ ์ ์ ์ฐํจ์ ๋ํด ์ธ๊ธํ ๋ถ๋ถ์ด๋ค. ์ถ์ํ ๋ถ๋ถ์์ ์ ์ฐํ๊ฒ ๋ง๋ค์๋ก ๋๋ฒ๊น
์ด ์ด๋ ค์์ง๋ค๊ณ ๋งํ๋๋ฐ ์ด ๋ถ๋ถ์ ํ ๋ฒ๋ ์๊ฐํด๋ณด์ง ๋ชปํ ๋ถ๋ถ์ด์๋ค. ๋ง์ ์๊ฐ์ ํ๊ฒ ๋ ์ฑํฐ์๋ค.
์ถ์ฒ
์ค๋ธ์ ํธ - ์ฝ๋๋ก ์ดํดํ๋ ๊ฐ์ฒด์งํฅ ์ค๊ณ
https://github.com/eternity-oop/object