Created
November 11, 2020 21:51
-
-
Save yunseop-kim/b20f7053aac39249ceff91068b221e82 to your computer and use it in GitHub Desktop.
오브젝트 2과 연습
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class MovieTheaters { | |
private _name: string; | |
private _theaters: Set<Theater> = new Set(); | |
private _screenings: Set<Screening> = new Set(); | |
constructor(name: string) { | |
this._name = name; | |
} | |
public createTheater(theater: Theater) { | |
this._theaters.add(theater); | |
} | |
public createScreening(screening: Screening) { | |
this._screenings.add(screening); | |
} | |
get name(): string { | |
return this._name; | |
} | |
get theaters(): Theater[] { | |
return Array.from(this._theaters); | |
} | |
get screenings(): Screening[] { | |
return Array.from(this._screenings); | |
} | |
} | |
class Theater { | |
private _name: string; | |
private _seats: number; | |
constructor(name: string, seats: number) { | |
this._name = name; | |
this._seats = seats; | |
} | |
get name(): string { | |
return this._name; | |
} | |
get seats(): number { | |
return this._seats; | |
} | |
public allocateSeats(audienceCount: number) { | |
if (this._seats - audienceCount > 0) | |
this._seats = this._seats - audienceCount; | |
else throw new Error("남은 좌석이 없습니다."); | |
} | |
} | |
class Screening { | |
private _theater: Theater; | |
private _movie: Movie; | |
private _whenScreened: string; | |
private _fee: number; | |
private _discountPolicy: DiscountPolicy; | |
constructor( | |
theater: Theater, | |
movie: Movie, | |
whenScreened: string, | |
fee: number, | |
discountPolicy: DiscountPolicy | |
) { | |
this._theater = theater; | |
this._movie = movie; | |
this._whenScreened = whenScreened; | |
this._fee = fee; | |
this._discountPolicy = discountPolicy; | |
} | |
get theater(): Theater { | |
return this._theater; | |
} | |
get fee(): number { | |
return this._fee; | |
} | |
get movie(): Movie { | |
return this._movie; | |
} | |
get whenScreened(): string { | |
return this._whenScreened; | |
} | |
public createReservation(customer: Customer, audienceCount: number) { | |
this._theater.allocateSeats(audienceCount); | |
const fee = this.fee - this._discountPolicy.calculateDiscountAmount(this); | |
return new Reservation(customer, this, fee, audienceCount); | |
} | |
} | |
class Movie { | |
private _name: string; | |
constructor(name: string) { | |
this._name = name; | |
} | |
get name() { | |
return this._name; | |
} | |
} | |
class Customer { | |
private _name: string; | |
constructor(name: string) { | |
this._name = name; | |
} | |
public reserve(screening: Screening, audienceCount: number) { | |
return screening.createReservation(this, audienceCount); | |
} | |
get name() { | |
return this._name; | |
} | |
} | |
abstract class DiscountPolicy { | |
private _conditions: DiscountCondition[] = new Array<DiscountCondition>(); | |
constructor(...args: DiscountCondition[]) { | |
this._conditions = args; | |
} | |
public calculateDiscountAmount(screening: Screening) { | |
for (const each of this._conditions) { | |
if (each.isSatisfiedBy()) { | |
return this.getDiscountAmount(screening); | |
} | |
} | |
return 0; | |
} | |
protected abstract getDiscountAmount(screening: Screening): number; | |
} | |
interface DiscountCondition { | |
isSatisfiedBy(): boolean; | |
} | |
class PercentDiscountPolicy extends DiscountPolicy { | |
private _percent: number; | |
constructor(percent: number, ...args: DiscountCondition[]) { | |
super(...args); | |
this._percent = percent; | |
} | |
protected getDiscountAmount(screening: Screening): number { | |
return screening.fee * this._percent; | |
} | |
} | |
class SequenceDiscountCondition implements DiscountCondition { | |
private _theater: Theater; | |
private _sequence: number; | |
constructor(theater: Theater, sequence: number) { | |
this._theater = theater; | |
this._sequence = sequence; | |
} | |
public isSatisfiedBy(): boolean { | |
return this._theater.seats === this._sequence; | |
} | |
} | |
class Reservation { | |
private _customer: Customer; | |
private _screening: Screening; | |
private _fee: number; | |
private _audienceCount: number; | |
constructor( | |
customer: Customer, | |
screening: Screening, | |
fee: number, | |
audienceCount: number | |
) { | |
this._customer = customer; | |
this._screening = screening; | |
this._fee = fee; | |
this._audienceCount = audienceCount; | |
} | |
get information() { | |
return { | |
customerName: this._customer.name, | |
movieName: this._screening.movie.name, | |
whenScreened: this._screening.whenScreened, | |
totalFee: this._fee * this._audienceCount, | |
}; | |
} | |
} | |
function main() { | |
const movieTheaters = new MovieTheaters("CGV 강남"); | |
const movie = new Movie("어벤져스"); | |
const theater = new Theater("상영관 1", 120); | |
movieTheaters.createTheater(theater); | |
const selectedTheater = movieTheaters.theaters[0]; | |
movieTheaters.createScreening( | |
new Screening( | |
selectedTheater, | |
movie, | |
"2020-11-11 13:00:00", | |
12000, | |
new PercentDiscountPolicy( | |
0.11, | |
new SequenceDiscountCondition(selectedTheater, 1) | |
) | |
) | |
); | |
movieTheaters.createScreening( | |
new Screening( | |
selectedTheater, | |
movie, | |
"2020-11-11 13:00:00", | |
12000, | |
new PercentDiscountPolicy( | |
0.11, | |
new SequenceDiscountCondition(selectedTheater, 1) | |
) | |
) | |
); | |
movieTheaters.createScreening( | |
new Screening( | |
selectedTheater, | |
movie, | |
"2020-11-11 16:00:00", | |
12000, | |
new PercentDiscountPolicy( | |
0.11, | |
new SequenceDiscountCondition(selectedTheater, 1) | |
) | |
) | |
); | |
movieTheaters.createScreening( | |
new Screening( | |
selectedTheater, | |
movie, | |
"2020-11-11 19:00:00", | |
12000, | |
new PercentDiscountPolicy( | |
0.11, | |
new SequenceDiscountCondition(selectedTheater, 1) | |
) | |
) | |
); | |
const customer = new Customer("김윤섭"); | |
const selectedScreening = movieTheaters.screenings[0]; | |
const reservation = customer.reserve(selectedScreening, 2); | |
console.log(reservation.information); | |
} | |
main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment