๐ Chapter 4: ์ค๊ณ ํ์ง๊ณผ ํธ๋ ์ด๋์คํ
- ํ๋ ฅ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํด ๋ฉ์์ง๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๊ฐ์ฒด ๋ค ์ฌ์ด์ ์ํธ์์ฉ์ด๋ค.
- ์ฑ ์์ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ํ๋ ฅํ๊ธฐ ์ํด ์ํํ๋ ํ๋์ด๋ค.
- ์ญํ ์ ๋์ฒด ๊ฐ๋ฅํ ์ฑ ์์ ์งํฉ์ด๋ค.
- ๊ฐ์ฒด์งํฅ ์ค๊ณ๋ ์ฌ๋ฐ๋ฅธ ๊ฐ์ฒด์๊ฒ ์ฌ๋ฐ๋ฅธ ์ฑ ์์ ํ ๋นํ๋ฉด์ ๋ฎ์ ๊ฒฐํฉ๋์ ๋์ ์์ง๋๋ฅผ ๊ฐ์ง ๊ตฌ์กฐ๋ฅผ ์ฐฝ์กฐํ๋ ํ๋์ด๋ค.
- ์ฑ ์์ ๊ฐ์ฒด์ ์ํ์์ ํ๋์ผ๋ก, ๋์๊ฐ ๊ฐ์ฒด์ ๊ฐ์ฒด ์ฌ์ด์ ์ํธ์์ฉ์ผ๋ก ์ค๊ณ ์ค์ฌ์ ์ด๋์ํค๊ณ , ๊ฒฐํฉ๋๊ฐ ๋ฎ๊ณ ์์ง๋๊ฐ ๋์ผ๋ฉฐ ๊ตฌํ์ ํจ๊ณผ์ ์ผ๋ก ์บก์ํํ๋ ๊ฐ์ฒด๋ค์ ์ฐฝ์กฐํ ์ ์๋ ๊ธฐ๋ฐ์ ์ ๊ณตํ๋ค.
๐ ๋ฐ์ดํฐ ์ค์ฌ์ ์ํ ์๋งค ์์คํ โ
- ๊ฐ์ฒด์ ์ํ๋ ๊ตฌํ์ ์ํ๋ค. ๊ตฌํ์ ๋ถ์์ ํ๊ธฐ ๋๋ฌธ์ ๋ณํ๊ธฐ ์ฝ๋ค. ์ํ๋ฅผ ๊ฐ์ฒด ๋ถํ ์ค์ฌ์ถ์ผ๋ก ์ผ์ผ๋ฉด ๊ตฌํ์ ๊ดํ ์ธ๋ถ์ฌํญ์ด ๊ฐ์ฒด์ ์ธํฐํ์ด์ค์ ์ค๋ฉฐ๋ค๊ฒ ๋์ด ์บก์ํ์ ์์น์ด ๋ฌด๋์ง๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ์ํ์ ๋ณ๊ฒฝ์ ์ธํฐํ์ด์ค์ ๋ณ๊ฒฝ์ ์ด๋ํ๋ฉฐ ์ด ์ธํฐํ์ด์ค์ ์์กดํ๋ ๋ชจ๋ ๊ฐ์ฒด์๊ฒ ๋ณ๊ฒฝ์ ์ํฅ์ด ํผ์ง๋ค. ๋๋ฌธ์ ๋ฐ์ดํฐ์ ์ด์ ์ ๋ง์ถ๋ ์ค๊ณ๋ ๋ณ๊ฒฝ์ ์ทจ์ฝํ ์ ๋ฐ์ ์๋ค.
- ๊ทธ์ ๋นํด ๊ฐ์ฒด์ ์ฑ ์์ ์ธํฐํ์ด์ค์ ์ํ๋ค. ๊ฐ์ฒด์ ์ฑ ์์ ๋๋ฌ๋ด๋ ์์ ์ ์ธ ์ธํฐํ์ด์ค ๋ค๋ก ์ฑ ์์ ์ํํ๋ ๋ฐ ํ์ํ ์ํ๋ฅผ ์บก์ํํจ์ผ๋ก์จ ๊ตฌํ ๋ณ๊ฒฝ์ ๋ํ ํ์ฅ์ด ์ธ๋ถ๋ก ํผ์ ธ๋๊ฐ๋ ๊ฒ์ ๋ฐฉ์งํ๋ค.
๐ ๋ฐ์ดํฐ๋ฅผ ์ค๋นํ์.โ
- ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ๋ ๊ฐ์ฒด๊ฐ ๋ด๋ถ์ ์ ์ฅํด์ผ ํ๋ ๋ฐ์ดํฐ๊ฐ ๋ฌด์์ธ๊ฐ๋ฅผ ๋ฌป๋ ๊ฒ์ผ๋ก ์์ํ๋ค.
Movie
์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ๊ฒฐ์ ํ๋ ๊ฒ์ผ๋ก ์ค๊ณ๋ฅผ ์์ํ๋ค.
public class Movie {
private String title; // ์ ๋ชฉ
private Duration runningTime; // ์์์๊ฐ
private Money fee; // ๊ธฐ๋ณธ ์๊ธ
private List<DiscountCondition> discountConditions;
private MovieType movieType;
private Money discountAmount;
private double discountPercent;
}
- ์ฌ๊ธฐ์ ์ฑ
์ ์ค์ฌ์
Movie
ํด๋์ค์์ ์ฐจ์ด์ ์discountConditions
,discountAmount
,discountPercent
์ดMovie
์์ ํฌํจ๋์ด ์๋ค. - ํ ์ธ ์ ์ฑ
์ ์ํ๋ณ๋ก ์ค์ง ํ๋๋ง ์ง์ ํ ์ ์๊ธฐ ๋๋ฌธ์
MovieType
์ผ๋ก ์ํ๋ฅผ ํ์ธํ๋ค.
public enum MovieType {
AMOUNT_DISCOUNT, // ๊ธ์ก ํ ์ธ ์ ์ฑ
PERCENT_DISCOUNT, // ๋น์จ ํ ์ธ ์ ์ฑ
NONE_DISCOUNT, // ๋ฏธ์ ์ฉ
}
- ์ด์ฒ๋ผ ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ์์๋ ๊ฐ์ฒด๊ฐ ํฌํจํด์ผ ํ๋ ๋ฐ์ดํฐ์ ์ง์คํ๋ค. (์ด ๊ฐ์ฒด๊ฐ ํฌํจํด์ผ ํ๋ ๋ฐ์ดํฐ๋ ๋ฌด์์ธ๊ฐ?)
- ์ด์ ์บก์ํ๋ฅผ ์ํด์ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ธ ๋ด๋ถ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ ์ ๊ทผ์์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์์ ์๋ฅผ ์ถ๊ฐํ๋ค.
public class Movie {
public MovieType getMovieType() {
return movieType;
}
public void setMovieType(MovieType movieType) {
this.movieType = movieType;
}
public Money getFee() {
return fee;
}
public List<DiscountCondition> getDiscountConditions() {
return Collections.unmodifiableList(discountConditions);
}
public void setDiscountConditions(List<DiscountCondition> discountConditions) {
this.discountConditions = discountConditions;
}
public Money getDiscountAmount() {
return discountAmount;
}
public void setDiscountAmount(Money discountAmount) {
this.discountAmount = discountAmount;
}
public double getDiscountPercent() {
return discountPercent;
}
public void setDiscountPercent(double discountPercent) {
this.discountPercent = discountPercent;
}
}
- ์ด์ ํ ์ธ ์กฐ๊ฑด์ ๊ตฌํํ๋ค. ์ํ ์๋งค ๋๋ฉ์ธ์ ์๋ฒ ์กฐ๊ฑด๊ณผ ๊ธฐ๊ฐ ์กฐ๊ฑด์ด ์๋ค.
public enum DiscountConditionType {
SEQUENCE, // ์๋ฒ ์กฐ๊ฑด
PERIOD // ๊ธฐ๊ฐ ์กฐ๊ฑด
}
- ํ ์ธ ์กฐ๊ฑด์ ๊ตฌํํ๋
DiscountCondition
์ ํ ์ธ ์กฐ๊ฑด์ ํ์ ์ ์ ์ฅํ ์ธ์คํด์ค ๋ณ์์ธtype
์ ํฌํจํ๋ค.
public class DiscountCondition {
private DiscountConditionType type;
private int sequence; // ์์ ์๋ฒ
private DayOfWeek dayOfWeek; // ์์ผ
private LocalTime startTime; // ์์ ์๊ฐ
private LocalTime endTime; // ์ข
๋ฃ ์๊ฐ
}
- ์บก์ํ๋ฅผ ํตํด ์ด ์์ฑ๋ค์ ํด๋์ค ์ธ๋ถ๋ก ๋
ธ์ถํด์๋ ์๋๊ธฐ ๋๋ฌธ์
Movie
ํด๋์ค์ฒ๋ผ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค.
public class DiscountCondition {
public DiscountConditionType getType() {
return type;
}
public void setType(DiscountConditionType type) {
this.type = type;
}
// ์๋ต...
}
- ์ด์ด์ Screening ํด๋์ค๋ฅผ ๊ตฌํํ๋ค. ์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ํฌํจํด์ผ ํ๋์ง๋ฅผ ๊ฒฐ์ ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ์บก์ํํ๊ธฐ ์ํด ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค.
public class Screening {
private Movie movie;
private int sequence;
private LocalDateTime whenScreened;
public Movie getMovie() {
return movie;
}
public void setMovie(Movie movie) {
this.movie = movie;
}
// ์๋ต...
}
- ์ํ ์๋งค ์์คํ
์ ๋ชฉ์ ์ ์ํ๋ฅผ ์๋งคํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
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;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
// ์๋ต...
}
- ๋ค์์
Customer
ํด๋์ค๋ก ๊ณ ๊ฐ์ ์ ๋ณด๋ฅผ ๋ณด๊ดํ๋ ํด๋์ค์ด๋ค.
public class Customer {
private String name;
private String id;
public Customer(String name, String id) {
this.id = id;
this.name = name;
}
}
๐ ์ํ๋ฅผ ์๋งคํ์โ
ReservationAgency
๋ ๋ฐ์ดํฐ ํด๋์ค๋ค์ ์กฐํฉํด์ ์ํ ์๋งค ์ ์ฐจ๋ฅผ ๊ตฌํํ๋ ํด๋์ค์ด๋ค.
public class ReservationAgency {
public Reservation reserve(Screening screening, Customer customer, int audienceCount) {
Movie movie = screening.getMovie();
boolean discountable = false;
// DiscountCondition์ ๋ํด ๋ฃจํ๋ฅผ ๋๋ฉด์ ํ ์ธ ๊ฐ๋ฅ ์ฌ๋ถ๋ฅผ ํ์ธ
for (DiscountCondition condition : movie.getDiscountConditions()) {
if (condition.getType() == DiscountConditionType.PERIOD) {
// ๊ธฐ๊ฐ ์กฐ๊ฑด
} else {
// ์๋ฒ ์กฐ๊ฑด
}
if (discountable) {
break;
}
}
Money fee;
if (discountable) { // ํ ์ธ ์ฌ๋ถ
Money discountAmount = Money.ZERO;
// ํ ์ธ ์ ์ฑ
์ ๋ฐ๋ผ ์๋งค ์๊ธ ๊ณ์ฐ
switch(movie.getMovieType()) {
case AMOUNT_DISCOUNT:
// ๊ธ์ก ํ ์ธ ์ ์ฑ
case PERCENT_DISCOUNT:
// ํ ์ธ ๋น์จ
case NONE_DISCOUNT:
// ํ ์ธ ์ ์ฑ
์ด ์ ์ฉ x
}
fee = movie.getFee().minus(discountAmount);
} else {
fee = movie.getFee();
}
return new Reservation(customer, screening, fee, audienceCount);
}
}
๐ ์ค๊ณ ํธ๋ ์ด๋์คํโ
๐ ์บก์ํโ
- ์ํ์ ํ๋์ ํ๋์ ๊ฐ์ฒด ์์ ๋ชจ์ผ๋ ์ด์ ๋ ๊ฐ์ฒด์ ๋ด๋ถ ๊ตฌํ์ ์ธ๋ถ๋ก๋ถํฐ ๊ฐ์ถ๊ธฐ ์ํด์์ด๋ค. (์ฌ๊ธฐ์ ๊ตฌํ์ด๋ ๋์ค์ ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ์ด๋ค ๊ฒ)
- ๋ณ๊ฒฝ๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ๋ถ๋ถ์ ๊ตฌํ, ์๋์ ์ผ๋ก ์์ ์ ์ธ ๋ถ๋ถ์ ์ธํฐํ์ด์ค๋ผ๊ณ ๋ถ๋ฅธ๋ค.
- ์บก์ํ๋ ์ธ๋ถ์์ ์ ํ์๊ฐ ์๋ ๋ถ๋ถ์ ๊ฐ์ถค์ผ๋ก์จ ๋์์ ๋จ์ํํ๋ ์ถ์ํ์ ํ ์ข ๋ฅ์ด๋ค. (์์ ์ ์ธ ์ธํฐํ์ด์ค ๋ค๋ก ์บก์ํํ๋ค.)
- ์บก์ํ๊ฐ ์ค์ํ ์ด์ ๋ ๋ถ์์ ํ ๋ถ๋ถ๊ณผ ์์ ์ ์ธ ๋ถ๋ถ์ ๋ถ๋ฆฌํด์ ๋ณ๊ฒฝ์ ์ํฅ์ ํต์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
- ์บก์ํ๋ ๋ณ๊ฒฝ ๊ฐ๋ฅ์ฑ์ด ๋์ ๋ถ๋ถ์ ๊ฐ์ฒด ๋ด๋ถ๋ก ์จ๊ธฐ๋ ์ถ์ํ ๊ธฐ๋ฒ์ด๋ค.
๐ ์์ง๋์ ๊ฒฐํฉ๋โ
- ์์ง๋๋ ๋ชจ๋์ ํฌํจ๋ ๋ด๋ถ ์์๋ค์ด ์ฐ๊ด๋ผ ์๋ ์ ๋๋ฅผ ๋ํ๋ธ๋ค. ๋ชจ๋ ๋ด์ ์์๋ค์ด ํ๋์ ๋ชฉ์ ์ ์ํด ๊ธด๋ฐํ๊ฒ ํ๋ ฅํ๋ค๋ฉด ๊ทธ ๋ชจ๋์ ๋์ ์์ง๋๋ฅผ ๊ฐ์ง๋ค.
- ๊ฒนํฉ๋๋ ์์กด์ฑ์ ์ ๋๋ฅผ ๋ํ๋ด๋ฉฐ ๋ค๋ฅธ ๋ชจ๋์ ๋ํด ์ผ๋ง๋ ๋ง์ ์ง์์ ๊ฐ๊ณ ์๋์ง๋ฅผ ๋ํ๋ด๋ ์ฒ๋์ด๋ค. ๋ค๋ฅธ ๋ชจ๋์ ๋ํด ๋๋ฌด ์์ธํ๊ฒ ์๊ณ ์๋ค๋ฉด ๋์ ๊ฒฐํฉ๋๋ฅผ ๊ฐ์ง๋ค.
- ๋์ ์์ง๋์ ๋ฎ์ ๊ฒฐํฉ๋๋ฅผ ๊ฐ์ง ์ค๊ณ๋ฅผ ์ถ๊ตฌํด์ผ ํ๋ ์ด์ ๋ ์ค๊ณ๋ฅผ ๋ณ๊ฒฝํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋ณ๊ฒฝ์ ๊ด์ ์์ ์์ง๋๋ ๋ณ๊ฒฝ์ด ๋ฐ์ํ ๋ ๋ชจ๋ ๋ด๋ถ์์ ๋ฐ์ํ๋ ๋ณ๊ฒฝ์ ์ ๋๋ก ์ธก์ ํ ์ ์๋ค. (ํ๋์ ๋ณ๊ฒฝ์ผ๋ก ์ธํด ๋ชจ๋ ์ ์ฒด๊ฐ ๋ณ๊ฒฝ๋๋ค๋ฉด ๊ฒฐํฉ๋๋ ๋๊ณ , ํ๋์ ๋ณ๊ฒฝ์ ํ๋์ ๋ชจ๋๋ง ๋ณ๊ฒฝ๋๋ค๋ฉด ๊ฒฐํฉ๋๋ ๋ฎ์ ๊ฒ์ด๋ค.)
- ์บก์ํ๋ฅผ ์งํค๋ฉด ๋ชจ๋ ์์ ์์ง๋๋ ๋์์ง๊ณ ๋ชจ๋ ์ฌ์ด์ ๊ฒฐํฉ๋๋ ๋ฎ์์ง๋ค.
๐ ๋ฐ์ดํฐ ์ค์ฌ์ ์ํ ์๋งค ์์คํ ์ ๋ฌธ์ ์ โ
Movie
์์ ์ ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ๋ ์ฑ ์ ์ค์ฌ ์ค๊ณ์ ๊ธฐ๋ฅ์ ์ผ๋ก๋ ์์ ํ ๋์ผํ์ง๋ง ์ค๊ณ ๊ด์ ์์๋ ์์ ํ ๋ค๋ฅด๋ค.- ๊ทผ๋ณธ์ ์ธ ์ฐจ์ด์ ์ ์บก์ํ๋ฅผ ๋ค๋ฃจ๋ ๋ฐฉ์์ด๋ค. ๋ฐ์ดํฐ ์ค์ฌ์ ์บก์ํ๋ฅผ ์๋ฐํ๊ณ ๊ฐ์ฒด์ ๋ด๋ถ ๊ตฌํ์ ์ธํฐํ์ด์ค์ ์ผ๋ถ๋ก ๋ง๋ ๋ค.
- ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ์ ๋ํ์ ์ธ ๋ฌธ์ ์ ์ ์ธ ๊ฐ์ง๋ก ์บก์ํ ์๋ฐ, ๋์ ๊ฒฐํฉ๋, ๋ฎ์ ์์ง๋์ด๋ค.
๐ ์บก์ํ ์๋ฐโ
- ๋ฐ์ดํฐ ์ค์ฌ์ผ๋ก ์ค๊ณํ
Movie
ํด๋์ค๋ ์ค์ง ๋ฉ์๋๋ฅผ ํตํด์๋ง ๊ฐ์ฒด์ ๋ด๋ถ ์ํ์ ์ ๊ทผํ ์ ์๋ค. ํ์ง๋ง ์ ๊ทผ์์ ์์ ์ ๋ฉ์๋๋ ๊ฐ์ฒด ๋ด๋ถ์ ์ํ์ ๋ํ ์ด๋ค ์ ๋ณด๋ ์บก์ํํ์ง ๋ชปํ๋ค.
public class Movie {
// Movie ๋ด๋ถ์ Money ํ์
์ fee๋ผ๋ ์ด๋ฆ์ ์ธ์คํด์ค ๋ณ์๊ฐ ์กด์ฌํ๋ค๋ ์ฌ์ค์
// ํผ๋ธ๋ฆญ ์ธํฐํ์ด์ค์ ๋
ธ๊ณจ์ ์ผ๋ก ๋๋ฌ๋ธ๋ค.
private Money fee;
public Money getFee() {
return fee;
}
public void setFee(Money fee) {
this.fee = fee;
}
}
- ์ด๋ฌํ ๊ทผ๋ณธ์ ์ธ ์์ธ์ ๊ฐ์ฒด๊ฐ ์ํํ ์ฑ ์์ด ์๋๋ผ ๋ด๋ถ์ ์ ์ฅํ ๋ฐ์ดํฐ์ ์ด์ ์ ๋ง์ท๊ธฐ ๋๋ฌธ์ด๋ค.
- ์ด๋ฌํ ์ ๊ทผ์์ ์์ ์์ ๊ณผ๋ํ๊ฒ ์์กดํ๋ ์ค๊ณ ๋ฐฉ์์ ์ถ์ธก์ ์ํ ์ค๊ณ ์ ๋ต์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ด ์ ๋ต์ ๊ฐ์ฒด๊ฐ ์ฌ์ฉ๋ ํ๋ ฅ์ ๊ณ ๋ คํ์ง ์๊ณ ๊ฐ์ฒด๊ฐ ๋ค์ํ ์ํฉ์์ ์ฌ์ฉ๋ ์ ์์ ๊ฒ์ด๋ผ๋ ๋ง์ฐํ ์ถ์ธก์ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋ฅผ ์งํํ๋ค.
๐ ๋์ ๊ฒฐํฉ๋โ
- ๊ฐ์ฒด์ ๋ด๋ถ ๊ตฌํ์ ๋ณ๊ฒฝํ์์๋ ์ด ์ธํฐํ์ด์ค์ ์์กดํ๋ ๋ชจ๋ ํด๋ผ์ด์ธํธ๋ค๋ ํจ๊ป ๋ณ๊ฒฝํด์ผ ํ๋ค.
public class ReservationAgency {
public Reservation reserve(Screening screening, Customer customer, int audienceCount) {
// ...
Money fee;
if (discountable) {
// ...
fee = movie.getFee().minus(discountAmount);
} else {
fee = movie.getFee();
}
return new Reservation(customer, screening, fee, audienceCount);
}
}
- ๋ง์ฝ ์ ์ฝ๋์์
fee
์ ํ์ ์ ๋ณ๊ฒฝํ๋ค๋ฉด ์ด๋ฅผ ์ํด์getFee
๋ฉ์๋์ ๋ฐํ ํ์ ๋ ํจ๊ป ์์ ํด์ผ ํ๋ค. ๊ทธ๋ฆฌ๊ณgetFee
๋ฅผ ํธ์ถํ๋ReservationAgency
์ ๊ตฌํ๋ ๋ณ๊ฒฝ๋ ํ์ ์ ๋ง๊ฒ ์์ ํด์ผ ํ๋ค. - ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ๋ ๊ฐ์ฒด์ ์บก์ํ๋ฅผ ์ฝํ์ํค๊ธฐ ๋๋ฌธ์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ฒด์ ๊ตฌํ์ ๊ฐํ๊ฒ ๊ฒฐํฉ๋๋ค.
ReservationAgency
๊ฐ ๋ชจ๋ ๋ฐ์ดํฐ ๊ฐ์ฒด์ ์์กดํ๊ณ ์๋ค.DiscountCondition
์ ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋๋ฉดReservationAgency
๋ ํจ๊ป ์์ ํด์ผ ํ๋ค.- ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ๋ ์ ์ฒด ์์คํ ์ ํ๋์ ๊ฑฐ๋ํ ์์กด์ฑ ๋ฉ์ด๋ฆฌ๋ก ๋ง๋ค์ด ๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ ์ด๋ค ๋ณ๊ฒฝ์ด๋ผ๋ ์ผ๋จ ๋ฐ์ํ๊ณ ๋๋ฉด ์์คํ ์ ์ฒด๊ฐ ์ํต์น ์๋ฐ์ ์๋ค.
๐ ๋ฎ์ ์์ง๋โ
ReservationAgency
๊ฐ ๋ค์๊ณผ ๊ฐ์ ์์ ์ฌํญ์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ์ ์ฝ๋๋ฅผ ์์ ํด์ผ ํ๋ค.- ํ ์ธ ์ ์ฑ ์ด ์ถ๊ฐ๋ ๊ฒฝ์ฐ
- ํ ์ธ ์ ์ฑ ๋ณ๋ก ํ ์ธ ์๊ธ์ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ์ด ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ
- ํ ์ธ ์กฐ๊ฑด์ด ์ถ๊ฐ๋ ๊ฒฝ์ฐ
- ํ ์ธ ์กฐ๊ฑด๋ณ๋ก ํ ์ธ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ ๋ฐฉ๋ฒ์ด ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ
- ์๋ฉ ์๊ธ์ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ์ด ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ
- ๋ฎ์ ์์ง๋๋ ๋ ๊ฐ์ง ์ธก๋ฉด์์ ์ค๊ณ์ ๋ฌธ์ ๋ฅผ ์ผ์ผํจ๋ค.
- ๋ณ๊ฒฝ์ ์ด์ ๊ฐ ์๋ก ๋ค๋ฅธ ์ฝ๋๋ค์ ํ๋์ ๋ชจ๋ ์์ ๋ญ์ณ๋์๊ธฐ ๋๋ฌธ์ ๋ณ๊ฒฝ๊ณผ ์๋ฌด ์๊ด์ด ์๋ ์ฝ๋๋ค์ด ์ํฅ์ ๋ฐ๊ฒ ๋๋ค.
- ํ๋์ ์๊ตฌ์ฌํญ ๋ณ๊ฒฝ์ ๋ฐ์ํ๊ธฐ ์ํด ๋์์ ์ฌ๋ฌ ๋ชจ๋์ ์์ ํด์ผ ํ๋ค.
๋จ์ผ ์ฑ ์ ์์น(SRP)
- ๋ชจ๋์ ์์ง๋๊ฐ ๋ณ๊ฒฝ๊ณผ ์ฐ๊ด์ด ์๋ค๋ ์ฌ์ค์ ๊ฐ์กฐํ๊ธฐ ์ํด ๋จ์ผ ์ฑ ์ ์์น์ด ๋์๋ค.
- ๋จ์ผ ์ฑ ์ ์์น์ ํด๋์ค๋ ๋จ ํ ๊ฐ์ง์ ๋ณ๊ฒฝ ์ด์ ๋ง ๊ฐ์ ธ์ผ ํ๋ค.
๐ ์์จ์ ์ธ ๊ฐ์ฒด๋ฅผ ํฅํดโ
๐ ์บก์ํ๋ฅผ ์ง์ผ๋ผโ
- ๊ฐ์ฒด๋ ์ค์ค๋ก์ ์ํ๋ฅผ ์ฑ ์์ ธ์ผ ํ๊ณ ์ธ๋ถ์์๋ ์ธํฐํ์ด์ค์ ์ ์๋ ๋ฉ์๋๋ฅผ ํตํด์๋ง ์ํ์ ์ ๊ทผํ ์ ์์ด์ผ ํ๋ค.
- ์ฌ๊ธฐ์ ๋งํ๋ ๋ฉ์๋๋ ์ ๊ทผ์๋ ์์ ์๊ฐ ์๋๋ผ ๊ฐ์ฒด์๊ฒ ์๋ฏธ ์๋ ๋ฉ์๋๋ ๊ฐ์ฒด๊ฐ ์ฑ ์์ ธ์ผ ํ๋ ๋ฌด์ธ๊ฐ๋ฅผ ์ํํ๋ ๋ฉ์๋์ด๋ค.
- ์ ๊ทผ์์ ์์ ์๋ฅผ ์ฌ์ฉํ ๋ฉ์๋์ ๋ฌธ์ ์ ์ ์ฝ๋ ์ค๋ณต์ด ๋ฐ์ํ ํ๋ฅ ์ด ๋๋ค. ๋ํ ๋ณ๊ฒฝ์ ์ทจ์ฝํ๋ค.
getBottom
์ด๋ผ๋ ๋ฉ์๋๋ฅผ ๋ณ๊ฒฝํ๋ฉด ์ด ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ ๊ณณ์์ ์์ ์ด ์ด๋ฃจ์ด์ ธ์ผ ํ๋ค. - ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์บก์ํ๋ฅผ ๊ฐํ์ํค๋ ๊ฒ์ด๋ค. ๊ฐ์ฒด๊ฐ ์๊ธฐ ์ค์ค๋ก ์ฑ ์์ ์ง๊ฒ ๋ง์ด๋ค.
๐ ์ค์ค๋ก ์์ ์ ๋ฐ์ดํฐ๋ฅผ ์ฑ ์์ง๋ ๊ฐ์ฒดโ
- ์ํ์ ํ๋์ ๊ฐ์ฒด๋ผ๋ ํ๋์ ๋จ์๋ก ๋ฌถ๋ ์ด์ ๋ ๊ฐ์ฒด ์ค์ค๋ก ์์ ์ ์ํ๋ฅผ ์ฒ๋ฆฌํ ์ ์๊ฒ ํ๊ธฐ ์ํด์์ด๋ค.
- ๊ฐ์ฒด ๋ด๋ถ์ ์ ์ฅ๋๋ ๋ฐ์ดํฐ๋ณด๋ค ๊ฐ์ฒด๊ฐ ํ๋ ฅ์ ์ฐธ์ฌํ๋ฉด์ ์ํํ ์ฑ
์์ ์ ์ํ๋ ์คํผ๋ ์ด์
์ด ๋ ์ค์ํ๋ค.
- ์ด ๊ฐ์ฒด๊ฐ ์ด ๋ค ๋ฐ์ดํฐ๋ฅผ ํฌํจํด์ผ ํ๋๊ฐ?
- ์ด ๊ฐ์ฒด๊ฐ ๋ฐ์ดํฐ์ ๋ํด ์ํํด์ผ ํ๋ ์คํผ๋ ์ด์ ์ ๋ฌด์์ธ๊ฐ?
- ๋ ์ง๋ฌธ์ ์กฐํฉํ๋ฉด ๊ฐ์ฒด์ ๋ด๋ถ ์ํ๋ฅผ ์ ์ฅํ๋ ๋ฐฉ์๊ณผ ์ ์ฅ๋ ์ํ์ ๋ํด ํธ์ถํ ์ ์๋ ์คํผ๋ ์ด์ ์ ์งํฉ์ ์ป์ ์ ์๋ค. ๋ค์ ๋งํด ์๋ก์ด ๋ฐ์ดํฐ ํ์ ์ ๋ง๋ค ์ ์๋ ๊ฒ์ด๋ค.
- ์ํ ์๋งค ์์คํ
์
ReservationAgency
๋ก ์์ด๋๊ฐ ๋ฐ์ดํฐ์ ๋ํ ์ฑ ์์ ์ค์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ ์๋ ๊ฐ์ฒด๋ก ์ฎ๊ฒจ๋ณธ๋ค. - ํ ์ธ ์กฐ๊ฑด์ ํํํ๋
DiscountCondition
๋ถํฐ ์์ํ๋ค. ์ฒซ ๋ฒ์งธ ์ง๋ฌธ์ธ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํด์ผ ํ๋ ์ง๋ฅผ ๋ฌป๋๊ฑด ์์์ ๊ฒฐ์ ํด ๋์๋ค. - ๋ ๋ฒ์งธ ์ง๋ฌธ์ ์ด ๋ฐ์ดํฐ์ ๋ํด ์ํํ ์ ์๋ ์คํฌ๋ ์ด์
์ด ๋ฌด์์ธ๊ฐ๋ฅผ ๋ฌป๋ ๊ฒ์ด๋ค. ํ ์ธ ์กฐ๊ฑด์๋ ์๋ฒ ์กฐ๊ฑด๊ณผ ๊ธฐ๊ฐ ์กฐ๊ฑด์ ๋ ๊ฐ์ง ์ข
๋ฅ๊ฐ ์กด์ฌํ๊ณ
DiscountCondition
์ ์๋ฒ ์กฐ๊ฑด์ผ ๊ฒฝ์ฐ์๋sequence
๋ฅผ ์ด์ฉํ๊ณ ๊ธฐ๊ฐ ์กฐ๊ฑด์ผ ๊ฒฝ์ฐ์๋dayOfWeek
,startTime
,endTime
์ ์ด์ฉํด ํ ์ธ ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ค. ๋ฐ๋ผ์ ๋ ๊ฐ์isDiscountable
์ด ํ์ํ ๊ฒ์ด๊ณ ๊ฐisDiscountable
๋ฉ์๋ ์์์type
์ ๊ฐ์ ์ด์ฉํด ํ์ฌ์ ํ ์ธ ์กฐ๊ฑด ํ์ ์ ๋ง๋ ์ ์ ํ ๋ฉ์๋๊ฐ ํธ์ถ๋๋์ง ํ๋จํ๋ค.
public class DiscountCondition {
// ๋ฐ์ดํฐ ์๋ต..
public DiscountConditionType getType() {
return type;
}
public boolean isDiscountable(DayOfWeek dayOfWeek, LocalTime time) {
if (type != DiscountConditionType.PERIOD) {
throw new IllegalArgumentException();
}
return this.dayOfWeek.equal(dayOfWeek) &&
this.startTime.compareTo(time) <= 0 &&
this.endTime.compareTo(time) >= 0;
}
public boolean isDiscountable(int sequence) {
if (type != DiscountConditionType.SEQUENCE) {
throw new IllegalArgumentException();
}
return this.sequence == sequence;
}
}
- ๋ค์์
Movie
๋ฅผ ๊ตฌํํ๋๋ฐ ์ฒซ ๋ฒ์งธ ์ง๋ฌธ์ ์ด๋ฏธ ๊ฒฐ์ ํ๋ค. - ๋ ๋ฒ์งธ ์ง๋ฌธ์
Movie
๋ ์ํ ์๊ธ์ ๊ณ์ฐํ๋ ์คํผ๋ ์ด์ ๊ณผ ํ ์ธ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ ์คํผ๋ ์ด์ ์ด ํ์ํ๋ค. ํ ์ธ ์ ์ฑ ์ ๊ธ์ก ํ ์ธ, ๋น์จ ํ ์ธ, ํ ์ธ ๋ฏธ์ ์ฉ์ ์ธ ๊ฐ์ง ํ์ ์ด ์๋ค. ๋๋ฌธ์ ํ ์ธ ์ ์ฑ ์ ํ์ ์ ๋ฐํํ๋getMovieType
๋ฉ์๋์ ์ ์ฑ ๋ณ๋ก ์๊ธ์ ๊ณ์ฐํ๋ ์ธ ๊ฐ์ง ๋ฉ์๋๋ฅผ ๊ตฌํํ๋ค.
public class Movie {
// ๋ฐ์ดํฐ ์๋ต..
public MovieType getMovieType() {
return movieType;
}
public Money calculateAmountDiscountedFee() {
if (movieType != MovieType.AMOUNT_DISCOUNT) {
throw new IllegalArgumentException();
}
return fee.minus(discountAmount);
}
// ๋ค ๋น์ท.. ์๋ต..
}
Movie
๋DiscountCondition
์ ๋ชฉ๋ก์ ํฌํจํ๊ธฐ ๋๋ฌธ์ ํ ์ธ ์ฌ๋ถ๋ฅผ ํ๋จํ๋ ์คํผ๋ ์ด์ ์ญ์ ํฌํจํด์ผ ํ๋ค.
public class Movie {
public boolean isDiscountable(LocalDateTime whenScreened, int sequence) {
for (DiscountCondition condition : discountConditions) {
// ๊ธฐ๊ฐ ์กฐ๊ฑด ๊ฒ์ฆ
if (condition.getType() == DiscountConditionType.PERIOD) {
if (condition.isDiscountable(whenScreened.getDayOfWeek(), whenScreened.toLocalTime())) {
return true;
}
} else {
// ์๋ฒ ์กฐ๊ฑด ๊ฒ์ฆ
if (condition.isDiscountable(sequence)) {
return false;
}
}
}
return false;
}
}
Screening
ํด๋์ค๋ ๋ ์ง๋ฌธ์ ๋ํด ์๊ฐํ๋ฉฐ ๊ตฌํํ๋ค.
public class Screening {
// ์๋ต..
public Money calculateFee(int audienceCount) {
switch (movie.getMovieType()) {
case AMOUNT_DISCOUNT:
// ...
case PERCENT_DISCOUNT:
// ...
case NONE_DISCOUNT:
// ...
}
}
}
ReservationAgency
๋Screening
์calculateFee
๋ฉ์๋๋ฅผ ํธ์ถํด ์๋งค ์๊ธ์ ๊ณ์ฐํ ํ ๊ณ์ฐ๋ ์๊ธ์ ์ด์ฉํดReservation
์ ์์ฑํ๋ค.
public class ReservationAgency {
public Reservation reserve(Screening screening, Customer customer, int audienceCount) {
Money fee = screening.calculateFee(audienceCount);
return new Reservation(customer, screening, fee, audienceCount);
}
}
- ์ด๋ ๊ฒ ํ๋ฉด ๋ด๋ถ ๊ตฌํ์ ๋ ๋ฉด๋ฐํ๊ฒ ์บก์ํํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ข๋ ๊ฐ์ ๋์๋ค. ๋ ๋ฒ์งธ ์ค๊ณ์์๋ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ํ์ํ ๋ฉ์๋๋ฅผ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ฒด ์ค์ค๋ก ๊ตฌํํ๊ณ ์๋ค. ๋ฐ๋ผ์ ์ด ๊ฐ์ฒด๋ค์ ์ค์ค๋ก๋ฅผ ์ฑ ์์ง๋ค๊ณ ๋งํ ์ ์๋ค.
๐ ํ์ง๋งใด ์ฌ์ ํ ๋ถ์กฑํ๋ค.โ
- ๋ ๋ฒ์งธ ์ค๊ณ ์ญ์ ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ ๋ฐฉ์์ ์ํ๋ค.
๐ ์บก์ํ ์๋ฐโ
- ์์ ๋ ๊ฐ์ฒด๋ค์ ์๊ธฐ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ์ค์ค๋ก ์ฒ๋ฆฌํ๋ค.
DiscountCondition
์ ์๊ธฐ ์์ ์ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํด ํ ์ธ ๊ฐ๋ฅ ์ฌ๋ถ๋ฅผ ์ค์ค๋ก ํ๋จํ๋ค.
public class DiscountCondition {
private DiscountConditionType type;
private int sequence;
private DayOfWeek dayOfWeek;
private LocalTime startTime;
private LocalTime endTime;
public DiscountConditionType getType() { }
public boolean isDiscountable(DayOfWeek dayOfWeek, LocalTime time) { }
public boolean isDiscountable(int sequence) { }
}
- ํ์ง๋ง
DiscountCondition
์ ๊ตฌํ๋ ๋ ๊ฐ์isDiscountable
๋ฉ์๋๋ฅผ ๋ณด๋ฉดDayOfWeek
ํ์ ์ ์์ผ ์ ๋ณด์LocalTime
ํ์ ์ ์๊ฐ ์ ๋ณด๊ฐ ์ธ์คํด์ค ๋ณ์๋ก ํฌํจ๋ผ ์๋ค๋ ์ฌ์ค์ ์ธํฐํ์ด์ค๋ฅผ ํตํด ์ธ๋ถ์ ๋ ธ์ถํ๊ณ ์๋ค. ์ด๋ ๊ฒ ๋๋ฉด ํด๋น ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ ํด๋ผ์ด์ธํธ๋ ํจ๊ป ์์ ํด์ผ ํ๋ค. Movie
๋ ์ญ์ ์บก์ํ๊ฐ ๋ถ์กฑํ๋ค. ๋ด๋ถ ๊ตฌํ์ ์ธํฐํ์ด์ค์ ๋ ธ์ถ์ํค๊ณ ์๋ค.calculateAmountDiscountedFee
,calculatePercentDiscountedFee
,calculateNoneDiscountedFee
์ด๋ผ๋ ์ธ ๊ฐ์ ๋ฉ์๋๋ ํ ์ธ ์ ์ฑ ์๋ ๊ธ์ก ํ ์ธ ์ ์ฑ , ๋น์จ ํ ์ธ ์ ์ฑ , ๋ฏธ์ ์ฉ์ ์ธ ๊ฐ์ง๊ฐ ์กด์ฌํ๋ค๋ ์ฌ์ค์ ๋๋ฌ๋ด๊ณ ์๋ค.
๐ ๋์ ๊ฒฐํฉ๋โ
- ์บก์ํ ์๋ฐ์ผ๋ก ์ธํด
DiscountCondition
์ ๋ด๋ถ ๊ตฌํ์ด ์ธ๋ถ๋ก ๋ ธ์ถ๋๊ธฐ ๋๋ฌธ์Movie
์DiscountCondition
์ฌ์ด์ ๊ฒฐํฉ๋๋ ๋์ ์๋ฐ์ ์๋ค.
public class Movie {
public boolean isDiscountable(LocalDateTime whenScreened, int sequence) {
for (DiscountCondition condition : discountConditions) {
if (condition.getType() == DiscountConditionType.PERIOD) {
if (condition.isDiscountable(whenScreened.getDayOfWeek(), whenScreened.toLocalTime())) {
return true;
}
} else {
if (condition.isDiscountable(sequence)) {
return false;
}
}
}
return false;
}
}
DiscountCondition
์ ๊ธฐ๊ฐ ํ ์ธ ์กฐ๊ฑด์ ๋ช ์นญ์ดPERIOD
์์ ๋ค๋ฅธ ๊ฐ์ผ๋ก ๋ณ๊ฒฝ๋๋ค๋ฉดMovie
๋ฅผ ์์ ํด์ผ ํ๋ค.DiscountCondition
์ ์ข ๋ฅ๊ฐ ์ถ๊ฐ๋๊ฑฐ๋ ์ญ์ ๋๋ค๋ฉดif ~ else
๊ตฌ๋ฌธ์ ์์ ํด์ผ ํ๋ค.
๐ ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ์ ๋ฌธ์ ์ โ
- ๋ ๋ฒ์งธ ์ค๊ณ๊ฐ ๋ณ๊ฒฝ์ ์ ์ฐํ์ง ๋ชปํ ์ด์ ๋ ์บก์ํ๋ฅผ ์๋ฐํ๊ธฐ ๋๋ฌธ์ด๋ค.
- ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ๊ฐ ๋ณ๊ฒฝ์ ์ทจ์ฝํ ์ด์ ๋ ๋ ๊ฐ์ง๋ค.
- ๋ณธ์ง์ ์ผ๋ก ๋๋ฌด ์ด๋ฅธ ์๊ธฐ์ ๋ฐ์ดํฐ์ ๊ดํด ๊ฒฐ์ ํ๋๋ก ๊ฐ์ํ๋ค.
- ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ์์๋ ํ๋ ฅ์ด๋ผ๋ ๋ฌธ๋งฅ์ ๊ณ ๋ คํ์ง ์๊ณ ๊ฐ์ฒด๋ฅผ ๊ณ ๋ฆฝ์ํจ ์ฑ ์คํผ๋ ์ด์ ์ ๊ฒฐ์ ํ๋ค.
๐ ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ์ ๊ฐ์ฒด์ ํ๋๋ณด๋ค๋ ์ํ์ ์ด์ ์ ๋ง์ถ๋ค.โ
- ๋ฐ์ดํฐ์ ์ด์ ์ด ๋ง์ถฐ์ ธ ์๋ค๋ฉด ๋ง์กฑ์ค๋ฌ์ด ์บก์ํ๋ฅผ ์ป๊ธฐ ์ด๋ ต๋ค.
- ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ๊ฒฐ์ ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐ ํ์ํ ์คํผ๋ ์ด์ ์ ๋์ค์ ๊ฒฐ์ ํ๋ ๋ฐฉ์์ ๋ฐ์ดํฐ์ ๊ดํ ์ง์์ด ๊ฐ์ฒด์ ์ธํฐํ์ด์ค์ ๊ณ ์ค๋ํ ๋๋ฌ๋๊ฒ ๋๋ค.
- ๊ฒฐ๋ก ์ ์ผ๋ก ๋ฐ์ดํฐ ์ค์ฌ์ ์ค๊ณ๋ ๋๋ฌด ์ด๋ฅธ ์๊ธฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ํด ๊ณ ๋ฏผํ๊ธฐ ๋๋ฌธ์ ์บก์ํ์ ์คํจํ๊ฒ ๋๋ค.
๐ ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ๋ ๊ฐ์ฒด๋ฅผ ๊ณ ๋ฆฝ์ํจ ์ฑ ์คํผ๋ ์ด์ ์ ์ ์ํ๋๋ก ๋ง๋ ๋คโ
- ๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ์์ ์ด์ ์ ๊ฐ์ฒด์ ์ธ๋ถ๊ฐ ์๋๋ผ ๋ด๋ถ๋ก ํฅํ๋ค.
- ์คํ ๋ฌธ๋งฅ์ ๋ํ ๊น์ด ์๋ ๊ณ ๋ฏผ ์์ด ๊ฐ์ฒด๊ฐ ๊ด๋ฆฌํ ๋ฐ์ดํฐ์ ์ธ๋ถ ์ ๋ณด๋ฅผ ๋จผ์ ๊ฒฐ์ ํ๋ค.