Skip to content

Instantly share code, notes, and snippets.

@yunseop-kim
Created November 11, 2020 21:51
Show Gist options
  • Save yunseop-kim/b20f7053aac39249ceff91068b221e82 to your computer and use it in GitHub Desktop.
Save yunseop-kim/b20f7053aac39249ceff91068b221e82 to your computer and use it in GitHub Desktop.
오브젝트 2과 연습
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