2024. 6. 29. 20:23ใ๋์
[์ค๋ธ์ ํธ 2์ฅ] - ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ
- ๋ชจ๋ ์ด๋ฏธ์ง์ ์ถ์ฒ๋ ์ค๋ธ์ ํธ(์กฐ์ฉํธ ์ ) ์ฑ ์ ๋๋ค.
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ํฅํด
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ํด๋์ค๋ฅผ ๋จผ์ ๊ณ ๋ฏผํ๋ ๊ฒ์ด ์๋๋ผ ๊ฐ์ฒด์ ์ง์คํด์ผ ํ๋ค. ๋ค์ ๋ ๊ฐ์ง๋ฅผ ์ง์คํด๋ณด์.
1) ์ด๋ค ํด๋์ค๊ฐ ํ์ํ์ง๋ฅผ ๊ณ ๋ฏผํ๊ธฐ ์ ์ ์ด๋ค ๊ฐ์ฒด๊ฐ ํ์ํ์ง ๊ณ ๋ฏผํ์. ์ด๋ค ๊ฐ์ฒด๋ค์ด ์ด๋ค ํ๋์ ํ๊ณ ์ด๋ค ์ํ๋ฅผ ๊ฐ์ง๋์ง๋ฅผ ๋จผ์ ๊ฒฐ์ ํ๋ค.
2) ๊ฐ์ฒด๋ฅผ ๋ ๋ฆฝ์ ์ธ ์กด์ฌ๊ฐ ์๋๋ผ ํ๋ ฅํ๋ ๊ณต๋์ฒด์ ์ผ์์ผ๋ก ๋ฐ๋ผ๋ด์ผ ํ๋ค.
๋๋ฉ์ธ์ ๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฅด๋ ํ๋ก๊ทธ๋จ ๊ตฌ์กฐ
๋๋ฉ์ธ์ ์ฌ์ฉ์์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ๋ ๋ถ์ผ๋ฅผ ์ผ์ปซ๋๋ค. ์ํ์๋งค ํ๋ก๊ทธ๋จ์์ '์ํ์๋ฉ'๋ ๋๋ฉ์ธ์ ์ํ๋ค.
๊ฐ์ฒด์งํฅ ํจ๋ฌ๋ค์์ด ๊ฐ๋ ฅํ ์ด์ ๋ ์๊ตฌ์ฌํญ์ ๋ถ์ํ๋ ์ด๊ธฐ ๋จ๊ณ๋ถํฐ ํ๋ก๊ทธ๋จ์ ๊ตฌํํ๋ ๋ง์ง๋ง ๋จ๊ณ๊น์ง ๋์ผํ ์ถ์ํ ๊ธฐ๋ฒ์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๊ตฌ์ฌํญ๊ณผ ํ๋ก๊ทธ๋จ์ ๊ฐ์ฒด๋ผ๋ ๋์ผํ ๊ด์ ์์ ๋ฐ๋ผ๋ณผ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ฉ์ธ์ ๊ตฌ์ฑํ๋ ๊ฐ๋ ๋ค์ด ํ๋ก๊ทธ๋จ์ ๊ฐ์ฒด์ ํด๋์ค๋ก ๋งค๋๋ฝ๊ฒ ์ฐ๊ฒฐ๋ ์ ์๋ค.
์ํ๋ ์ฌ๋ฌ ๋ฒ ์์๋ ์ ์๊ณ , ์์์ ์ฌ๋ฌ ๋ฒ ์๋งค ๋ ์ ์๋ค๋ ๊ฒ์ ์ ์ ์๋ค. ๋ํ ์ํ๋ ํ ์ธ์ ์ฑ ์ด ์์ ์๋ ์๊ณ , ํ ์ธ ์ ์ฑ ์ด ์กด์ฌํ๋ค๋ฉด ํ ์ธ ์กฐ๊ฑด์ด ๋ฐ๋์ ํ๋ ์ด์์ด ์กด์ฌํด์ผ ํจ์ ์ ์ ์๋ค.
๋๋ฉ์ธ์ ๊ตฌ์กฐ๋ฅผ ํด๋์ค์ ๋งค์นญ ์ํค๋ฉด ๋ค์๊ณผ ๊ฐ์์ง๋ค.
ํด๋์ค ๊ตฌํํ๊ธฐ
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 geetStartTime() {
return whenScreened;
}
public boolean isSequence(int sequence) {
return this.sequence == sequence;
}
public Money getMovieFee() {
return movie.getFee();
}
}
ํด๋์ค๋ฅผ ์์ฑํ ๋ ์ค์ํ ๊ฒ์ ๋ด๋ถ์ ์ธ๋ถ๋ฅผ ๊ฒฝ๊ณ์ง๋ ๊ฒ์ด๋ค. ์ด๋ฌํ ๊ฒฝ๊ณ๊ฐ ๋ช ํํ๋ฉด ๋ช ํํ ์๋ก ๊ฐ์ฒด ์ค์ค๋ก๊ฐ ์ํ๋ฅผ ์ฝ๊ฒ ๋ณ๊ฒฝํ ์ ์๊ธฐ ๋๋ฌธ์ ์์จ์ฑ์ ๋ณด์ฅํ๋ค. ์ด๋ ๊ฒ ๋๋ฉด ํ๋ก๊ทธ๋๋จธ์๊ฒ ๊ตฌํ์ ์์ ๋ฅผ ์ ๊ณตํ๊ฒ ๋๋ค. -> ์ด๋ ๊ณณ์์ ๋ณ๊ฒฝ๋ ์ง๋ฅผ ๋ช ํํ๊ฒ ์๋๊น ๋ณ๊ฒฝ์ ์์ (๊ตฌํ์ ์์ )๊ฐ ์๊ธฐ๋ ๊ฒ.
๊ฐ์ฒด๋ 1) '์ํ'์ 'ํ๋'์ ํจ๊ป ๊ฐ์ง๋ ๋ณตํฉ์ ์ธ ์กด์ฌ์ด๋ฉด์ 2) ์ค์ค๋ก ํ๋จํ๊ณ ํ๋ํ๋ '์์จ์ ์ธ ์กด์ฌ'์ด๋ค.
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ค์ ๋๋ถ๋ถ ์ ๊ทผ์ ์ด์๋ฅผ ์ง์ํ๋ค.
๊ฐ์ฒด ๋ด๋ถ๋ฅผ ํต์ ํ๋ ์ด์ ๋ ๊ฐ์ฒด๋ฅผ ์์จ์ ์ธ ์กด์ฌ๋ก ๋ง๋ค๊ธฐ ์ํด์๋ค. ๊ฐ์ฒด์งํฅ์ ํต์ฌ์ ์ค์ค๋ก ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ , ํ๋จํ๊ณ , ํ๋ํ๋ ์์จ์ ์ธ ๊ฐ์ฒด๋ค์ ๊ณต๋์ฒด๋ฅผ ๊ตฌ์ฑํ๋ ๊ฒ์ด๋ค. ์ธ๋ถ์์ ๊ฐ์ฒด์ ์ํ๋ฅผ ๋ณ๊ฒฝํ๊ฒ ๋๋ค๋ฉด ๊ฐ์ฒด๊ฐ ์์จ์ ์ธ ์กด์ฌ๊ฐ ๋์ง ๋ชปํ๋ค.
์ง์ ๊ฐ์ ํ์ง ๋ง๊ณ ์ํ๋ ๊ฑธ ์์ฒญํ๊ณ ์ค์ค๋ก ์ต์ ์ ๊ฒฐ์ ์ ๋ด๋ฆฌ๋๋ก ๊ธฐ๋ค๋ฆฌ์.
์ธํฐํ์ด์ค์ ๊ตฌํ์ ๋ถ๋ฆฌํด์ผ ํ๋ ๊ฐ์ฅ ํฐ ์ด์ ๋ ๋ณ๊ฒฝ์ ์ฉ์ดํ๊ธฐ ์ํด์์์ ๊ธฐ์ตํ์.
ํด๋ผ์ด์ธํธ๋ ์ธํฐํ์ด์ค๋ฅผ ํตํด์ ๊ตฌ์ฒด์ ์ธ ๊ฐ์ฒด์ ๋ด๋ถ ๊ตฌํ์ ์ ํ์๊ฐ ์๋ค. ์๊ฐ์ ์ฝ์ธ ์ ์ด๋ค. ๋๋ถ์ด ๊ตฌํ๋ด์ฉ์ ์๊ณ ๋ฆฌ์ฆ์ ์ถ๊ฐํ๊ฑฐ๋ ๋ก์ง์ ๋ฐ๊พธ๋๋ผ๋ ํด๋ผ์ด์ธํธ์ ์ฝ๋๋ ๋ณํ์ง ์๋๋ค. ๋ฐ๋ผ์ ํด๋์ค ์์ฑ์๋ ์ธํฐํ์ด์ค์ ๊ตฌํ์ ๊น๋ํ๊ฒ ๋ถ๋ฆฌํ๊ธฐ ์ํด ๋ ธ๋ ฅํด์ผ ํ๋ค.
ํ๋ ฅํ๋ ๊ฐ์ฒด๋ค์ ๊ณต๋์ฒด
public class Money {
public static final Money ZERO = Money.wons(0);
private final BigDecimal amount;
public static Money wons(BigDecimal amount) {
return new Money(BigDecimal.valueOf(amount));
}
}
Money ํ์ ๋์ ์ long ํ์ ์ ์ฌ์ฉํ ์๋ ์์ง๋ง '๊ธ์ก'์ด๋ผ๋ ์๋ฏธ๋ฅผ ์ ๋ฌํ ์๋ ์๋ค. ๋ํ ๊ธ์ก๊ณผ ๊ด๋ จ๋ ๋ก์ง์ Moneyํ์ ์ ๋ด์ ์ ์๊ธฐ ๋๋ฌธ์ ์ค๋ณต์ฝ๋๋ฅผ ์ค์ผ ์ ์๋ค. ๊ฐ์ฒด์งํฅ์ ์ฅ์ ์ ๊ฐ์ฒด๋ฅผ ์ด์ฉํด ๋๋ฉ์ธ์ ์๋ฏธ๋ฅผ ํ๋ถํ๊ฒ ํํํ ์ ์๋ค๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ์๋ฏธ๋ฅผ ์ข ๋ ๋ช ์์ ์ด๊ณ ๋ถ๋ช ํ๊ฒ ํํํ ์ ์๋ค๋ฉด ๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ ํด๋น ๊ฐ๋ ์ ๊ตฌํํ๋ผ. ๊ทธ ๊ฐ๋ ์ด ๋น๋ก ์ธ์คํด์ค ๋ณ์๋ฅผ ํฌํจํ๋๋ผ๋ ๋ง์ด๋ค.
๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ํธ์์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ฉ์์ง๋ฅผ ์ ์กํ๋ ๊ฒ ๋ฟ์ด๋ค. ์ด์ ์ ์ฌํ ๊ฐ๋ ์ผ๋ก ๋ฉ์๋๊ฐ ์๋๋ฐ, ๋ฉ์๋๋ ์์ ๋ ๋ฉ์์ง๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์์ ๋ง์ ๋ฐฉ๋ฒ์ ์๋ฏธํ๋ค.
ํ ์ธ ์๊ธ ๊ตฌํ๊ธฐ
์ํ์๋งค ๊ธ์ก์ ๊ตฌํ ํ ์ธ ์ ์ฑ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ณด์.
๋จผ์ ํ ์ธ ์ ์ฑ ์ ๊ธ์ก ํ ์ธ ์ ์ฑ ๊ณผ ๋น์จ ํ ์ธ ์ ์ฑ ์ผ๋ก ๊ตฌ๋ถ๋๋ค. ๋ ๊ฐ์ง ํ ์ธ ์ ์ฑ ์ ๊ฐ๊ฐ AmountDiscountPolicy์ PercentDiscountPolicy๋ก ๊ตฌ๋ถํ๋ค. ๋ ํด๋์ค๋ ์ ์ฌํ๊ธฐ ๋๋ฌธ์ ์ค๋ณต ์ฝ๋๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ํด ๊ณตํต ์ฝ๋๋ฅผ ๋ณด๊ดํ ์ฅ์๊ฐ ํ์ํ๋ค. ๋ฐ๋ผ์ ์ถ์ ํด๋์ค๋ฅผ ์ฌ์ฉํด๋ณด์.
public abstract class DiscountPolicy {
private List<DiscountCondition> conditions = new ArrayList<>();
public DiscountPolicy(DiscountCondition ... conditions) {
this.conditions = conditions;
}
public Money calculateDiscountAmount(Screening screening) {
for(DiscountCondition each : conditions) {
if (each.isSatisFiedBy(screening)) {
return getDiscountAmount(screening)
}
}
return Money.ZERO;
}
abstract Money getDiscountAmount(Screening screening);
}
ํ ์ธ ์กฐ๊ฑด์ ๋ง์กฑํ๋ DiscountCondition์ด ํ๋๋ผ๋ ์กด์ฌํ๋ ๊ฒฝ์ฐ์๋ '์ถ์ ๋ฉ์๋'์ธ getDiscountAmount๋ฅผ ํธ์ถํด์ ํ ์ธ ์๊ธ์ ๊ณ์ฐํ๋ค.
DiscountPolicy๋ ํ ์ธ ์ฌ๋ถ์ ๊ณ์ฐํ๋ ํ๋ฆ์ ์ ์ํ์ง๋ง ์ค์ ๋ก ๊ณ์ฐํ๋ ๋ถ๋ถ์ ์์ ํด๋์ค์์ ์ค๋ฒ๋ผ์ด๋ฉ ํ ๋ฉ์๋์ ์์ํ๋ค. ์ด์ฒ๋ผ ๋ถ๋ชจํด๋์ค์ ๊ธฐ๋ณธ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํ๊ณ ์ค๊ฐ์ ํ์ํ ์ฒ๋ฆฌ๋ฅผ ์์ ํด๋์ค์ ์์ํ๋ ๋์์ธ ํจํด์ 'TEMPLATE METHOD'(ํ ํ๋ฆฟ ๋ฉ์๋) ํจํด์ด๋ผ๊ณ ํ๋ค.
DiscountCondition์ ์๋ฐ์ ์ธํฐํ์ด์ค๋ก ๊ตฌํํ๋ค.
public interface DiscountCondition {
boolean isSatisfied(Screening screening);
}
๊ทธ๋ฆฌ๊ณ ์ด ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ์์์กฐ๊ฑด๊ณผ ๊ธฐ๊ฐ ์กฐ๊ฑด์ ๊ตฌํํ๋ค.
public class SequenceCondition implements DiscountCondition {
private int sequence;
public SequenceCondition(int sequence) {
this.sequence = sequence;
}
@Override
public boolean isSatisfied(Screening screening) {
return false;
}
}
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;
}
@Override
public boolean isSatisfied(Screening screening) {
return screening.getStartTime().getDayOfWeek().equals(dayOfWeek) &&
startTime.compareTo(screening.getStartTime().toLocalTime()) <= 0 &&
endTime.compareTo(screening.getStartTime().toLocalTime()) >= 0;
}
}
๋ค์์ผ๋ก๋ ํ ์ธ ์ ์ฑ ์ ๊ตฌํํ์. AmountDiscountPolicy๋ DiscountPolicy์ ์์ ํด๋์ค๋ก์ ํ ์ธ ์กฐ๊ฑด์ ๋ง์กฑํ ๊ฒฝ์ฐ ์ผ์ ํ ๊ธ์ก์ ํ ์ธํด์ค๋ค.
public class AmountDiscountPolicy implements DiscountPolicy {
private Money discountAmount;
public AmountDiscountPolicy(Money discountAmount, DiscountCondition ... conditions) {
super(conditions);
this.discountAmount = discountAmount;
}
@Override
Money getDiscountAmount(Screening screening) {
return discountAmount;
}
}
PercentDiscountPolicy ์ญ์ getDiscountAmount ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ๊ตฌํํ๋ค.
public class PercentDiscountPolicy extends DiscountPolicy {
private double percent;
public PercentDiscountPolicy(double percent, DiscountCondition ... conditions) {
super(conditions);
this.percent = percent;
}
@Override
protected Money getDiscountAmount(Screening screening) {
return screening.getMovieFee().times(percent);
}
}
์ ์ฑ ์ ๊ดํ ๊ตฌํํด๋์ค๋ค์ ์ถ์ํด๋์ค๋ฅผ ์์๋ฐ๊ณ ์๊ธฐ ๋๋ฌธ์ super๋ฅผ ํตํด ๋ถ๋ชจํด๋์ค๋ฅผ ์ด๊ธฐํํด์ค๋ค.
์ ์ฝ๋๋ค์ ์์ฑ์๋ฅผ ํตํด์ ์ด๊ธฐํ์ ํ์ํ ์ ๋ณด๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ฌํ๋๋ก ๊ฐ์ ํ๊ณ ์๋ค. ์ด๋ฅผ ํตํด ํ ์ธ ์ ์ฑ ์ ํ ์ํ๋น ํ ๊ฐ๋ง ์ ์ฉํ๊ณ , ํ ์ธ ์กฐ๊ฑด์ ์ฌ๋ฌ ๊ฐ๋ฅผ ์ ์ฉํ ์ ์๋๋ก ํด์ค๋ค.
์ด์ ํด๋ผ์ด์ธํธ ์ธก์์ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์์ง๋ค.
Movie titanic = new Movie("ํ์ดํ๋",
Duration.ofMinutes(180),
Money.wons(11000),
new PercentDiscountPolicy(0.1),
new PeriodCondition(DayOfWeek.TUESDAY, LocalTime.of(14, 0), LocalTime.of(16, 59)),
new SequenceCondition(2),
new PeriodCondition(DayOfWeek.THURSDAY, LocalTime.of(10, 0), LocalTime.of(13, 59))
);
ํ์ดํ๋ ์ํ๊ฐ ๋น์จ ํ ์ธ์ ์ฑ ์ ์ฌ์ฉํ๊ณ ๋ ๊ฐ์ ํ ์ธ์กฐ๊ฑด๊ณผ ํ๊ฐ์ ์์์กฐ๊ฑด์ด ์๋ ๊ฒ์ ํ๋์ ๋ณผ ์ ์๋ค.
์์๊ณผ ๋คํ์ฑ
Movie๋ DiscountPolicy ํด๋์ค์ ์ฐ๊ฒฐ๋์ด ์๋ค. ์ฝ๋ ์์ค์์๋ DiscountPolicy์ ์ฐ๊ฒฐ๋์ด ์์ง๋ง ์ค์ ์ฝ๋๊ฐ ์คํ๋ ๋๋ ๊ตฌํํด๋์ค์ธ AmountDiscountPolicy๋ PercentDiscountPolicy์ ์ฐ๊ฒฐ๋์ด ์๋ค.
์ฌ๊ธฐ์ ์ด์ผ๊ธฐํ๊ณ ์ถ์ ๊ฒ์ ์ฝ๋์ ์์กด์ฑ๊ณผ ์คํ ์์ ์ ์์กด์ฑ์ด ์๋ก ๋ค๋ฅผ ์ ์๋ค๋ ๊ฒ์ด๋ค. ์ ์ฐํ๊ณ , ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ํ์ฅ ๊ฐ๋ฅํ ๊ฐ์ฒด์งํฅ ์ค๊ณ๊ฐ ๊ฐ์ง๋ ํน์ง์ ์ฝ๋์ ์์กด์ฑ๊ณผ ์คํ ์์ ์ ์์กด์ฑ์ด ๋ค๋ฅด๋ค.
ํ์ง๋ง ์ด ๋ ์์ ์ ๊ฐ๊ทน์ด ๋ฉ์ด์ง ์๋ก ์ฝ๋๋ฅผ ์ดํดํ๊ธฐ๊ฐ ์ด๋ ค์์ง๋ค. ๋ฐ๋ฉด์ ์ดํด๋ ์ด๋ ต์ง๋ง ์ ์ฐํ๊ณ ํ์ฅ ๊ฐ๋ฅํด์ง๋ค. ์ญ์ ์ค๊ณ๋ ํธ๋ ์ด๋์คํ์ ์ฐ๋ฌผ์ด๋ค.
๋ฌด์กฐ๊ฑด ์ ์ฐํ ์ค๊ณ๋, ๋ฌด์กฐ๊ฑด ๊ฐ๋ ์ฑ์ด ์ข์ ์ค๊ณ๋ ์ ๋ต์ด ์๋๋ค. ํญ์ ์ด ๋ ๊ฐ์ง ๊ธฐ๋ก์์ ๊ณ ๋ฏผํด์ผ ํ๋ค. (๋ฌผ๋ก ๋ ๋ค ์ง์ผ์ง๋ฉด ๋ ์ข๊ฒ ์ง๋ง ๋ง์ด๋ค.)
์ฐจ์ด์ ์ํ ํ๋ก๊ทธ๋๋ฐ
๋ถ๋ชจ์ ํด๋์ค์ ๋ค๋ฅธ ๋ถ๋ถ๋ง ์ถ๊ฐํด์ ์๋ก์ด ํด๋์ค๋ฅผ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ๋ง๋๋ ๋ฐฉ๋ฒ์ '์ฐจ์ด์ ์ํ ํ๋ก๊ทธ๋๋ฐ'์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์ฐจ์ด์ ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ค๋ณต์ฝ๋ ์์ด ์์ฝ๊ฒ ๋ถ๋ชจํด๋์ค์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ฉด์ ๊ธฐ๋ฅ์ ํ์ฅํ ์ ์๋ค. ์ด๋ฅผ ๊ฐ๋ฅ์ผํ๋ ๊ฒ ์ค ํ๋๊ฐ ์์์ด๋ค. ํ์ง๋ง ์์์ด ํญ์ ์ข์ ๊ฒ์ ์๋๋ค. ์์ ํด๋์ค๊ฐ ๋ถ๋ชจ ํด๋์ค์ ๊ฒฐํฉ๋๊ฐ ๋์์ง๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ ๋ค์์ ์ดํด๋ณธ๋ค.
์์์ด ๊ฐ์น ์๋ ์ด์ ๋ ๋ถ๋ชจ ํด๋์ค์ ์ธํฐํ์ด์ค๋ฅผ ์์ ํด๋์ค์์ ์ ๋ถ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ ํด๋ผ์ด์ธํธ ์ ์ฅ์์ ์์ ์ด ๋ฉ์์ง๋ฅผ ์ ๋ฌํ๋ ๊ฐ์ฒด๊ฐ ๋๊ตฌ์ธ์ง ํฌ๊ฒ ์๊ดํ์ง ์์๋ ๋๊ธฐ ๋๋ฌธ์ ๋คํ์ฑ์ ์ฑ๊ฒจ๊ฐ ์ ์๋ค.
DiscountPolicyํ์ ์ AmountDiscountPolicy๊ฐ ํ ๋น ๊ฐ๋ฅํ ์ด์ ๋ '์ ์บ์คํ '์ด ์ผ์ด๋๊ธฐ ๋๋ฌธ์ด๋ค. ์ฆ ๋ถ๋ชจํ์ ์ผ๋ก ํ์ ์ ์ ํ๋ ๊ฒ์ด๋ค.
์ธ์ด์ฐจ์์์ ์ ์บ์คํ ์ ์ง์ํ๋ค๋ฉด ๋คํ์ฑ์ ์งํฌ ์ ์๊ฒ๋๋ค. ๋คํ์ฑ์ ๊ฐ์ฒด์๊ฒ ๋์ผํ ๋ฉ์์ง๋ฅผ ๋์ง์ง๋ง ์ค์ ๋ก ์ด๋ค ๋ฉ์๋๊ฐ ์คํ๋ ์ง๋ ์์ ํ ๊ฐ์ฒด์ ํ์ ์ ๋ฐ๋ผ ๋ฐ๋๋ ๊ฒ์ ์๋ฏธํ๋ค.
๋คํ์ฑ์ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋จ์ ์ปดํ์ผ ์๊ฐ ์์กด์ฑ๊ณผ ์คํ ์๊ฐ ์์กด์ฑ์ด ๋ค๋ฅผ ์ ์๋ค๋ ์ฌ์ค์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ค. ์ฆ ์คํ ์์ ์ ์ฌ์ฉํ ๋ฉ์๋๋ฅผ ๊ฒฐ์ ํ๊ธฐ ๋๋ฌธ์ ๋ค์ํ ํํ๋ก ๋์ ์ํฌ ์ ์๋ ๊ฒ์ด๋ค. ์ด๋ฌํ ๋์์ '์ง์ฐ ๋ฐ์ธ๋ฉ' ํน์ '๋์ ๋ฐ์ธ๋ฉ'์ด๋ผ๊ณ ํ๋ค.
์ธํฐํ์ด์ค์ ๋คํ์ฑ
DiscountPolicy๋ผ๋ ์ถ์ ํด๋์ค๋ก ๋คํ์ฑ์ ์ถฉ์กฑํ์ง๋ง ์ธํฐํ์ด์ค๋ฅผ ํตํด์๋ ๋คํ์ฑ์ ์ถฉ์กฑ์ํฌ ์ ์๋ค.
๋ด๋ถ ๊ตฌํ์ ๊ณต์ ํ ํ์์์ด ์์ํ๊ฒ ์ธํฐํ์ด์ค๋ง ๊ณต์ ํ๋๋ก ํ๋ ๊ฒ์ด๋ค.
DiscountPolicy ๋ด๋ถ์ ์ธ์คํด์ค์ ๋ณ์๋ก ์๋ DiscountConfition์ด ๋ฐ๋ก ๊ทธ ์๋ค.
์ถ์ํ์ ์ ์ฐ์ฑ
ํ ์ธ ์ ์ฑ ๊ณผ ํ ์ธ ์กฐ๊ฑด์ ๊ตฌ์ฒด์ ์ธ ํญ๋ชฉ๋ค์์ ๊ณตํต์ ์ธ ํน์ง์ ๋ฝ์์ ์ฌ์ฉํ๋ ์ถ์ํ๋ ๊ฐ๋ ์ด๋ค. ์ด๋ฅผ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด ์ธก๋ฉด์์ ๋ณด์๋ฉด ์ด๋ค์ด ๋ ์ถ์์ ์ธ ์ด์ ๋ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ถ์ํ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ค์ ๋ ๊ฐ์ง ์ฅ์ ์ด ์๋ค.
1) ์๊ตฌ์ฌํญ์ ์ ์ฑ ์ ๋์ ์์ค์์ ์์ ๊ฐ๋ฅํ๋ค.
2) ์ค๊ณ๊ฐ ๋ ์ ์ฐํด์ง๋ค.
์ถ์ํ๋ ํ์ ๋ง ๋ณด๊ณ ๊ด๊ณ๋ฅผ ๋ดค์๋ ํต์ฌ์ ์ธ ํ๋ฆ์ ํ ๋์ ๋ณผ ์ ์๋ค.
'์ํ๋ ํ๋์ ์ ์ฑ ์ด ์๊ณ ์ฌ๋ฌ๊ฐ์ ํ ์ธ ์กฐ๊ฑด์ด ์๋ค'
์ด๋ฅผ ํตํด ์ธ๋ถ์ ์ธ ๋ด์ฉ์ ๋ฌด์ํ ์ฑ ํ๋ ฅ ํ๋ฆ์ ๊ธฐ์ ํ ์ ์๋ค. ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ์ค๊ณ์ ๊ธฐ๋ณธ์ ์ด๋ฃจ๋ '๋์์ธ ํจํด'๊ณผ 'ํ๋ ์์ํฌ' ๋ชจ๋ ์ถ์ํ๋ฅผ ์ด์ฉํด ์์ ์ ์ฑ ์ ์ ์ํ๋ ๊ฐ์ฒด์งํฅ ๋ฉ์ปค๋์ฆ์ ํ์ฉํ๊ณ ์๋ค.
๋ฐ๋ก ์ด ์ด์ ์ ํ์ธํ๊ธฐ ์ํด ์๊ตฌ์ฌํญ ์ถ๊ฐ๋ก ํ์ธํด๋ณด์.
ํ ์ธ์ ์ฑ ์ด ์๋ ์ํ๋ ์๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์ฒซ๋ฒ์งธ ๋์์ ์์ธ ์ผ์ด์ค๋ฅผ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค.
public class Movie {
public Money calculateMovieFee(Screening screening) {
if (discountPolicy == null) {
return fee;
}
return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
}
๊ธฐ์กด์๋ ํ ์ธ ์ ์ฑ ์ ์ฑ ์์ง๋ ์ชฝ์ด DiscountPolicy ์ธก์ ์์์ง๋ง ์ ์ฝ๋๋ Movie์์ ์ฑ ์์ ์ง๊ณ ์๊ธฐ์ ์ง๊ธ๊น์ง์ ํ๋ ฅ๋ฐฉ์์ด ๊นจ์ง๋ค. ํญ์ ์์ธ์ผ์ด์ค๋ฅผ ์ต์ํํ๊ณ ์ผ๊ด์ฑ์ ์ ์งํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ํํด์ผ ํ๋ค.
์ด๋ฅผ ์ํด NoneDiscountPolicy ํด๋์ค๋ฅผ ์ถ๊ฐํด๋ณด์.
public class NoneDiscountPolicy extends DiscountPolicy {
@Override
Money getDiscountAmount(Screening screening) {
return Money.ZERO;
}
}
์ด๋ก์จ Movie๋ฅผ ์์ ํ์ง ์๊ณ NoneDiscountPolicy ํด๋์ค๋ฅผ ์ถ๊ฐํ๋ ๊ฒ๋ง์ผ๋ก ๊ธฐ๋ฅ์ ํ์ฅํ๋ค.
์ถ์ํ๊ฐ ์ ์ฐํ ์ค๊ณ๋ฅผ ๊ฐ๋ฅ์ผ ํ๋ ์ด์ ๋ ์ค๊ณ๊ฐ ๊ตฌ์ฒด์ ์ธ ์ํฉ์ ๊ฒฐํฉ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ๋๋ฌธ์ด๋ค.
DiscountPolicy ์ญ์๋ ํน์ ํ ์ธ ์กฐ๊ฑด์ ๋ฌถ์ฌ์์ง ์์๋ฐ ์ด๋ ์ถ์์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ฅผ '์ปจํ ์คํธ ๋ ๋ฆฝ์ฑ'์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
๊ฒฐ๋ก ์ ๊ฐ๋จํ๋ค. ์ ์ฐ์ฑ์ด ํ์ํ ๊ณณ์ ์ถ์ํ๋ฅผ ์ฌ์ฉํ์.
์์
์์์ ๊ฐ์ฅ ํฐ ๋ฌธ์ ์ ์ ์บก์ํ๋ฅผ ์๋ฐํ๋ ๊ฒ์ด๋ค. ์์์ ์ํด์๋ ๋ถ๋ชจ ํด๋์ค์ ๋ด๋ถ ๊ตฌ์กฐ๋ฅผ ์ ์๊ณ ์์ด์ผ ํ๋ค.
AmountDiscountMovie์ PercentDiscountMovie๋ฅผ ๊ตฌํํ๋ ๊ฐ๋ฐ์๋ Movie์ calculateMovieFee ๋ฉ์๋ ์์์ ์ถ์ ๋ฉ์๋์ธ getDiscountAmount ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค๋ ์ฌ์ค์ ์๊ณ ์์ด์ผ ํ๋ค. ์ด๋ ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ถ๋ชจ ํด๋์ค์ ๋ณ๊ฒฝ์ด ์์ํด๋์ค์ ๋ณ๊ฒฝ์ ์ด๋ํ๊ฒ ๋๋ค.
๋ ๋ฒ์งธ ๋จ์ ์ ์ค๊ณ๊ฐ ์ ์ฐํ์ง ์๋ค๋ ๊ฒ์ด๋ค. ์์์ ๋ถ๋ชจ ํด๋์ค์ ์์ ํด๋์ค์ ๊ด๊ณ๊ฐ ์ปดํ์ผ ์์ ์ ๊ฒฐ์ ๋๋ค. ๋ฐ๋ผ์ ์คํ ์์ ์ ๊ฐ์ฒด์ ์ข ๋ฅ๋ฅผ ๋ณ๊ฒฝํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๋ค.
์์์ ์ฌ์ฉํ ์ค๊ณ๋ ์คํ ์์ ์ ๋ณ๊ฒฝํ๋ ค๋ฉด ์ธ์คํด์ค ์์ฑ ํ ์ํ๋ฅผ ๋ณต์ฌํด์ผ ํ๋ค. ํ์ง๋ง ์์์ ์ดํด๋ณธ ๋ฐฉ๋ฒ์ ์ด์ฉํ๋ฉด ์คํ์์ ์ ํ ์ธ ์ ์ฑ ์ ๊ฐ๋จํ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค. ์ด์ฒ๋ผ ์ธํฐํ์ด์ค์ ์ ์๋ ๋ฉ์์ง๋ฅผ ํตํด์๋ง ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ 'ํฉ์ฑ'์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค.
ํฉ์ฑ์ ์์์ด ๊ฐ์ง๋ ๋ ๊ฐ์ง ๋ฌธ์ ์ ์ ๋ชจ๋ ํด๊ฒฐํ๋ค. ์ธํฐํ์ด์ค์ ์ ์๋ ๋ฉ์์ง๋ฅผ ํตํด์๋ง ์ฌ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๊ตฌํ์ ํจ๊ณผ์ ์ผ๋ก ์บก์ํํ๋ค. ๋ํ ์ธ์คํด์ค๋ฅผ ๊ต์ฒดํ๋ ๊ฒ์ด ์ฝ๊ธฐ ๋๋ฌธ์ ์ค๊ณ๋ฅผ ์ ์ฐํ๊ฒ ๋ง๋ ๋ค. ๋ฐ๋ผ์ ์ฝ๋ ์ฌ์ฌ์ฉ์ ์ํด์๋ ์์๋ณด๋ค๋ ํฉ์ฑ์ ์ ํธํ๋ ๊ฒ์ด ๋ ์ข์ ๋ฐฉ๋ฒ์ด๋ค.
๊ทธ๋ ๋ค๊ณ ์์์ด ์ค์ํ์ง ์์ ๊ฒ์ ์๋๋ค. ๋ค์์ ์์๋ณผ ๊ฒ์ธ๋ฐ ์์์ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๊ฒ์ด ์๋๋ผ ํ์ ๊ณ์ธต์ ์ถ๊ฐํ๊ธฐ ์ํด ์ฌ์ฉํด์ผ ํ๋ค. Money์ DiscountPolicy๋ ํฉ์ฑ ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋์ด ์๊ณ , DiscountPolicy์ AmountDiscountPolicy๋ ์์ ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋์ด ์๋ค. ์ด์ฒ๋ผ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ํฉ์ฑ ๊ด๊ณ๋ฅผ ์ฌ์ฉํ์ง๋ง ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ ๋คํ์ฑ์ ์ํด ์์๊ณผ ํฉ์ฑ์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๋ค.
'๋์' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์ค๋ธ์ ํธ 4์ฅ] - ์ค๊ณ ํ์ง๊ณผ ํธ๋ ์ด๋ ์คํ (0) | 2024.07.07 |
---|---|
[์ค๋ธ์ ํธ 3์ฅ] - ์ญํ , ์ฑ ์, ํ๋ ฅ (0) | 2024.07.07 |
[์ค๋ธ์ ํธ 1์ฅ] - ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์ (0) | 2024.06.29 |