์์ ํด๋์ค๋ฅผ ์ด์ฉํ ๋, ์ ํด๋์ค์์ ๋ฐ๋ณต๋๋ ๊ฒ์ด ์๊ณ ์ด๋ค ํน์ ๊ธฐ๋ฅ๋ง ์์ ํด๋์ค์์ ๊ทธ ์ํ๊ฐ ๋ฌ๋ผ์ง๋ค๋ฉด
Abstract ํด๋์ค๋ฅผ ๋ง๋ค ๊ฒ์ ๊ณ ๋ คํด๋ณด์.
abstract ํด๋์ค์ abstract ํจ์๋ ํ๋ก๊ทธ๋๋จธ์ ์ค์๋ฅผ ์ฌ์ ์ ์๋ฐฉํด์ฃผ๋ ๋งค๋ ฅ์ ์ธ ๊ธฐ๋ฅ๋ค์ ๊ฐ์ถ๊ณ ์๋ค.
abstract ํด๋์ค์ abstract ํจ์๋ฅผ ์ด์ฉํ์ ๋์ ์ด์ ์,
๋ฌด์์ ์ค๋ฒ๋ผ์ด๋ฉ + super()ํธ์ถํ๊ธฐ ํ๋์ ์ด๋ ์ ๋ ๋์ฒดํ๋ฉด์
์์ํด๋์ค์์ ๋ถ๋ชจํด๋์ค์ ์ฐจ๋ณํ๋๋ ์ถ์ํ ํจ์๋ค์ ๋ฐ๋์ ๊ตฌํํ ๊ฒ์ ๊ฐ์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์๋์ ๊ฐ์ ์ฝ๋๋ฒ ์ด์ค๋ถํฐ ์์ํ๋ค.
// //์ปคํผ๋จธ์ ๋ง๋ค๊ธฐ
type CoffeeCup = {
orderShot: number;
hasMilk?: boolean;
hasSalt?: boolean;
};
interface CoffeeMaker {
makeCoffee(shots: number): CoffeeCup;
}
//์ผ๋ฐ ์ฐ์ ๊ฑฐํ๊ธฐ
class CheapMilkSteamer {
//(1)์ฐ์ ๊ฑฐํ์ ๋ง๋๋ ๋ด๋ถ ํจ์
private steamMilk(): void {
console.log("๋ชฝ๊ธ๋ชฝ๊ธ ํฌ์ญํฌ์ญํ ์ฐ์ ํผ");
}
//(2)๋ง๋ค์ด์ง ์ปคํผ์ปต์ ๋ฐ์์, ๋ง๋ค์ด์ง ์ฐ์ ๊ฑฐํ(1)์ ๋ถ์ด์ ์ด ์ปคํผ์ปต์ ๋ค์ ๋ฆฌํดํ๋ ํจ์
addMilkform(cup: CoffeeCup): CoffeeCup {
this.steamMilk();
return {
...cup,
hasMilk: true,
};
}
}
//์๊ธ๋ฏน์
class SaltMixer {
//(1)์๊ธ์ ์ง๋ ๋ด๋ถ ํจ์
private getSalt() {
console.log("์๊ธ์ ํ๊ผฌ์ง ์ง์๋ค");
return true;
}
//(2)๋ง๋ค์ด์ง ์ปคํผ์ปต์ ๋ฐ์์, ์ง์ ์๊ธ(1)์ ๋ฟ๋ ค์ ์ด ์ปคํผ์ปต์ ๋ค์ ๋ฆฌํดํ๋ ํจ์
addSalt(cup: CoffeeCup): CoffeeCup {
const salt = this.getSalt();
return {
...cup,
hasSalt: salt,
};
}
}
// CoffeeMaker ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ CoffeMachine ํด๋์ค์ด๋ค.////////////////////////////
class CoffeMachine implements CoffeeMaker {
protected static ONE_SHOT_CAPSULE: number = 3;
protected static ONE_CUP_WATER: number = 10;
static makeMachine(beans: number, water: number): CoffeMachine {
return new CoffeMachine(beans, water);
}
public constructor(
protected capsule: number = 3,
protected water: number = 10
) {}
makeCoffee(orderShot: number): CoffeeCup {
this.checkMaterials(orderShot);
console.log("์บก์์ฐ๊ธฐ ์ " + this.capsule);
this.useCapsule(orderShot);
console.log("๋ฌผ์ฐ๊ธฐ ์ " + this.water);
this.useWater();
this.heatWater();
return this.extract(orderShot);
}
protected checkMaterials(orderShot: number) {
if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
throw new Error(`์ปคํผ์บก์ ๋ถ์กฑ!!! ํ์ฌ ๋ณด์ ์บก์ : ${this.capsule}`);
}
if (this.water < CoffeMachine.ONE_CUP_WATER) {
throw new Error(`๋ฌผ ๋ถ์กฑ!!! ๋จ์ ๋ฌผ ${this.water}`);
}
}
clean(): void {
console.log("์ปคํผ๋จธ์ ํ๊ตฌ๋ ์ค!");
}
private extract(shots: number): CoffeeCup {
return {
orderShot: shots,
hasMilk: false,
};
}
private heatWater() {
console.log("๋ฌผ ๋์ด๋ ์ค...");
}
private useCapsule(shot: number) {
console.log("์บก์์ฐ๋ฌ์์ต๋๋ค.");
this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
console.log("์บก์ ์ฐ๊ณ ๋ ํ" + this.capsule);
}
protected useWater() {
console.log("๋ฌผ์ฐ๋ฌ์์ต๋๋ค.");
this.water -= CoffeMachine.ONE_CUP_WATER;
console.log("๋ฌผ์ฐ๊ณ ๋ ํ " + this.water);
}
addCapsule(capsule: number) {
this.capsule += capsule;
}
fulfillWater(water: number) {
this.water += water;
}
get Water(): number {
return this.water;
}
get Capsule(): number {
return this.capsule;
}
}
// CoffeMachine ํด๋์ค๋ฅผ ์์๋ฐ์ CafeLatteMachine ํด๋์ค์ด๋ค.
class CafeLatteMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private milkFrother: CheapMilkSteamer
) {
super(capsule, water);
}
makeCoffee(orderShot: number): CoffeeCup {
const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์ ์๋น, ๋ฌผ ์๋น, ๋ฌผ ๊ฐ์ด ๋ค ๋๋๊ณ ์์ฑ๋ ์ปคํผ๊ฐ ๋ฐํ
const saltAdded = this.milkFrother.addMilkform(coffee);
return this.milkFrother.addMilkform(saltAdded);
}
}
// CoffeMachine ํด๋์ค ๋ฅผ ์์๋ฐ์ saltCoffeeMachine ํด๋์ค์ด๋ค.
class saltCoffeeMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private saltTopping: SaltMixer
) {
super(capsule, water);
}
makeCoffee(orderShot: number): CoffeeCup {
const coffee = super.makeCoffee(orderShot);
return this.saltTopping.addSalt(coffee);
}
}
const machines: CoffeeMaker[] = [
new CoffeMachine(25, 25),
new CafeLatteMachine(15, 25, new CheapMilkSteamer()),
new saltCoffeeMachine(5, 10, new SaltMixer()),
];
machines.forEach((machine) => {
console.log("------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------");
console.log(machine.makeCoffee(1));
});
<์ถ์ํด๋์ค ์์ ์ ์ถ๋ ฅ ๊ฒฐ๊ณผ>
------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------
์บก์์ฐ๊ธฐ ์ 25
์บก์์ฐ๋ฌ์์ต๋๋ค.
์บก์ ์ฐ๊ณ ๋ ํ22
๋ฌผ์ฐ๊ธฐ ์ 25
๋ฌผ์ฐ๋ฌ์์ต๋๋ค.
๋ฌผ์ฐ๊ณ ๋ ํ 15
๋ฌผ ๋์ด๋ ์ค...
{ orderShot: 1, hasMilk: false }
------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------
์บก์์ฐ๊ธฐ ์ 15
์บก์์ฐ๋ฌ์์ต๋๋ค.
์บก์ ์ฐ๊ณ ๋ ํ12
๋ฌผ์ฐ๊ธฐ ์ 25
๋ฌผ์ฐ๋ฌ์์ต๋๋ค.
๋ฌผ์ฐ๊ณ ๋ ํ 15
๋ฌผ ๋์ด๋ ์ค...
๋ชฝ๊ธ๋ชฝ๊ธ ํฌ์ญํฌ์ญํ ์ฐ์ ํผ
๋ชฝ๊ธ๋ชฝ๊ธ ํฌ์ญํฌ์ญํ ์ฐ์ ํผ
{ orderShot: 1, hasMilk: true }
------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------
์บก์์ฐ๊ธฐ ์ 5
์บก์์ฐ๋ฌ์์ต๋๋ค.
์บก์ ์ฐ๊ณ ๋ ํ2
๋ฌผ์ฐ๊ธฐ ์ 10
๋ฌผ์ฐ๋ฌ์์ต๋๋ค.
๋ฌผ์ฐ๊ณ ๋ ํ 0
๋ฌผ ๋์ด๋ ์ค...
์๊ธ์ ํ๊ผฌ์ง ์ง์๋ค
๋ถ๋ชจํด๋์ค
class CoffeMachine implements CoffeeMaker {
protected static ONE_SHOT_CAPSULE: number = 3;
protected static ONE_CUP_WATER: number = 10;
static makeMachine(beans: number, water: number): CoffeMachine {
return new CoffeMachine(beans, water);
}
public constructor(
protected capsule: number = 3,
protected water: number = 10
) {}
makeCoffee(orderShot: number): CoffeeCup {
this.checkMaterials(orderShot);
console.log("์บก์์ฐ๊ธฐ ์ " + this.capsule);
this.useCapsule(orderShot);
console.log("๋ฌผ์ฐ๊ธฐ ์ " + this.water);
this.useWater();
this.heatWater();
return this.extract(orderShot);
}
protected checkMaterials(orderShot: number) {
if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
throw new Error(`์ปคํผ์บก์ ๋ถ์กฑ!!! ํ์ฌ ๋ณด์ ์บก์ : ${this.capsule}`);
}
if (this.water < CoffeMachine.ONE_CUP_WATER) {
throw new Error(`๋ฌผ ๋ถ์กฑ!!! ๋จ์ ๋ฌผ ${this.water}`);
}
}
clean(): void {
console.log("์ปคํผ๋จธ์ ํ๊ตฌ๋ ์ค!");
}
private extract(shots: number): CoffeeCup {
return {
orderShot: shots,
hasMilk: false,
};
}
private heatWater() {
console.log("๋ฌผ ๋์ด๋ ์ค...");
}
private useCapsule(shot: number) {
console.log("์บก์์ฐ๋ฌ์์ต๋๋ค.");
this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
console.log("์บก์ ์ฐ๊ณ ๋ ํ" + this.capsule);
}
protected useWater() {
console.log("๋ฌผ์ฐ๋ฌ์์ต๋๋ค.");
this.water -= CoffeMachine.ONE_CUP_WATER;
console.log("๋ฌผ์ฐ๊ณ ๋ ํ " + this.water);
}
addCapsule(capsule: number) {
this.capsule += capsule;
}
fulfillWater(water: number) {
this.water += water;
}
get Water(): number {
return this.water;
}
get Capsule(): number {
return this.capsule;
}
}
์์ํด๋์ค 1,2
// CoffeMachine ํด๋์ค๋ฅผ ์์๋ฐ์ CafeLatteMachine ํด๋์ค์ด๋ค.
class CafeLatteMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private milkFrother: CheapMilkSteamer
) {
super(capsule, water);
}
makeCoffee(orderShot: number): CoffeeCup {
const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์ ์๋น, ๋ฌผ ์๋น, ๋ฌผ ๊ฐ์ด ๋ค ๋๋๊ณ ์์ฑ๋ ์ปคํผ๊ฐ ๋ฐํ
const saltAdded = this.milkFrother.addMilkform(coffee);
return this.milkFrother.addMilkform(saltAdded);
}
}
์ง๊ธ์ const coffee = super.makeCoffee(orderShot); ์์ผ๋ก ๋ถ๋ชจ ํด๋์ค์ ํจ์๋ฅผ ํธ์ถํด์ฃผ์ง๋ง
์ค์๋ก ์ด ์ฝ๋๋ฅผ ์์ฑํ์ง ์์ผ๋ฉด?
makeCoffee๋ฅผ ์ํ ํต์ฌ ๋จ๊ณ๋ฅผ ๋์น ์๊ฐ ์๊ฒ ๋๋ค.
์ด๋ฐ ์ค์๋ค์ ๋ฐฉ์งํ๊ณ ์ถ๋ค๋ฉด ์์ ํ๊ฒ Abstract class๋ฅผ ๋ง๋๋ ๊ฒ์ ๊ณ ๋ คํด๋ณผ ์ ์๋ค.
// CoffeMachine ํด๋์ค ๋ฅผ ์์๋ฐ์ saltCoffeeMachine ํด๋์ค์ด๋ค.
class saltCoffeeMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private saltTopping: SaltMixer
) {
super(capsule, water);
}
makeCoffee(orderShot: number): CoffeeCup {
const coffee = super.makeCoffee(orderShot);
return this.saltTopping.addSalt(coffee);
}
}
abstract class
// CoffeeMaker ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ CoffeMachine ํด๋์ค์ด๋ค.////////////////////////////
abstract class CoffeMachine implements CoffeeMaker {
์ด๊ฒ์ ์ถ์์ ์ธ ํด๋์ค์ด๋ค. ์ด ์์ฒด๋ก๋ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค ์ ์๋ค.
์ถ์์ ์ธ ๋ถ๋ชจํด๋์ค๋ก์ ๋ณธ์ง์ ์ผ๋ก ํ์ํ ๊ฒ๋ค์ ์ ์ํด๋๊ณ ,
์์ํด๋์ค๋ง๋ค ๋ฌ๋ผ์ง ์ ์๋ ํ๋์ด ์๋ค๋ฉด ๊ทธ ํ๋์ ํด๋นํ๋ ํจ์ ์์ abstract ํค์๋๋ฅผ ๋ถ์ฌ์ฃผ์.
abstract extract(shots: number): CoffeeCup {
return {
orderShot: shots,
hasMilk: false,
};
}
ํค์๋๋ฅผ ๋ถ์ฌ์ฃผ์ ๋ง์ ๋นจ๊ฐ์ค์ด ๊ทธ์ด์ง๋ค.
์์์ ๋นจ๊ฐ ๋ฐ์ค์ด ๊ทธ์ด์ง abstrct extract ํจ์๋ ์์ ํด๋์ค์์ ์์ ํด๋์ค๋ง๋ค ๋ค๋ฅด๊ฒ ๊ตฌํ์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์
์ ๊ทผ์ง์ ์ ํ์๋ private๊ฐ ์๋ protected๋ก ๋ฌ์์ฃผ์ด์ผ ํ๊ณ ,
์ถ์์ ์ธ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ ๊ตฌํ ์ฌํญ์ ์์ฑํ๋ฉด ์๋๋ค.
๋ฐ๋ก ์ด๋ ๊ฒ
protected abstract extract(shots: number): CoffeeCup;
extract ํจ์๋ ์ถ์ํด๋์ค์ ์ถ์ํจ์์ด๊ธฐ ๋๋ฌธ์ ์ถ์ํจ์ ๊ตฌํ ํด๋์ค์์ ๊ตฌํํด์ฃผ์ด์ผ ํ๋ค.
๊ธฐ์กด ์์ ํด๋์ค์์ makeCoffeeํจ์๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ ํ์๊ฐ ์์ด์ก๋ค.
๋์ ์ extract ํจ์๋ฅผ ๊ตฌํํด์ฃผ๋๋ก ํ๋ค.
<๋ณ๊ฒฝ ์ >
// CoffeMachine ํด๋์ค๋ฅผ ์์๋ฐ์ CafeLatteMachine ํด๋์ค์ด๋ค.
class CafeLatteMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private milkFrother: CheapMilkSteamer
) {
super(capsule, water);
}
makeCoffee(orderShot: number): CoffeeCup {
const coffee = super.makeCoffee(orderShot); //๊ธฐ๋ณธ์ ์ธ ์บก์ ์๋น, ๋ฌผ ์๋น, ๋ฌผ ๊ฐ์ด ๋ค ๋๋๊ณ ์์ฑ๋ ์ปคํผ๊ฐ ๋ฐํ
const saltAdded = this.milkFrother.addMilkform(coffee);
return this.milkFrother.addMilkform(saltAdded);
}
}
// CoffeMachine ํด๋์ค ๋ฅผ ์์๋ฐ์ saltCoffeeMachine ํด๋์ค์ด๋ค.
class saltCoffeeMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private saltTopping: SaltMixer
) {
super(capsule, water);
}
makeCoffee(orderShot: number): CoffeeCup {
const coffee = super.makeCoffee(orderShot);
return this.saltTopping.addSalt(coffee);
}
}
<๋ณ๊ฒฝ ํ>
// CoffeMachine ํด๋์ค๋ฅผ ์์๋ฐ์ CafeLatteMachine ํด๋์ค์ด๋ค.
// tslint:disable-next-line: max-classes-per-file
class CafeLatteMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private milkFrother: CheapMilkSteamer
) {
super(capsule, water);
}
protected extract(shots: number): CoffeeCup {
const blackCoffee = {
orderShot: shots,
};
return this.milkFrother.addMilkform(blackCoffee);
}
}
// CoffeMachine ํด๋์ค ๋ฅผ ์์๋ฐ์ saltCoffeeMachine ํด๋์ค์ด๋ค.
class saltCoffeeMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private saltTopping: SaltMixer
) {
super(capsule, water);
}
protected extract(shots: number): CoffeeCup {
const blackCoffee = {
orderShot: shots,
};
return this.saltTopping.addSalt(blackCoffee);
}
}
<์ง๊ธ๊น์ง ์งํ๋ ์ ์ฒด ์ฝ๋>
// //์ปคํผ๋จธ์ ๋ง๋ค๊ธฐ
type CoffeeCup = {
orderShot: number;
hasMilk?: boolean;
hasSalt?: boolean;
};
interface CoffeeMaker {
makeCoffee(shots: number): CoffeeCup;
}
//์ผ๋ฐ ์ฐ์ ๊ฑฐํ๊ธฐ
class CheapMilkSteamer {
//(1)์ฐ์ ๊ฑฐํ์ ๋ง๋๋ ๋ด๋ถ ํจ์
private steamMilk(): void {
console.log("๋ชฝ๊ธ๋ชฝ๊ธ ํฌ์ญํฌ์ญํ ์ฐ์ ํผ");
}
//(2)๋ง๋ค์ด์ง ์ปคํผ์ปต์ ๋ฐ์์, ๋ง๋ค์ด์ง ์ฐ์ ๊ฑฐํ(1)์ ๋ถ์ด์ ์ด ์ปคํผ์ปต์ ๋ค์ ๋ฆฌํดํ๋ ํจ์
addMilkform(cup: CoffeeCup): CoffeeCup {
this.steamMilk();
return {
...cup,
hasMilk: true,
};
}
}
//์๊ธ๋ฏน์
class SaltMixer {
//(1)์๊ธ์ ์ง๋ ๋ด๋ถ ํจ์
private getSalt() {
console.log("์๊ธ์ ํ๊ผฌ์ง ์ง์๋ค");
return true;
}
//(2)๋ง๋ค์ด์ง ์ปคํผ์ปต์ ๋ฐ์์, ์ง์ ์๊ธ(1)์ ๋ฟ๋ ค์ ์ด ์ปคํผ์ปต์ ๋ค์ ๋ฆฌํดํ๋ ํจ์
addSalt(cup: CoffeeCup): CoffeeCup {
const salt = this.getSalt();
return {
...cup,
hasSalt: salt,
};
}
}
// CoffeeMaker ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ CoffeMachine ํด๋์ค์ด๋ค.////////////////////////////
abstract class CoffeMachine implements CoffeeMaker {
protected static ONE_SHOT_CAPSULE: number = 3;
protected static ONE_CUP_WATER: number = 10;
public constructor(
protected capsule: number = 3,
protected water: number = 10
) {}
makeCoffee(orderShot: number): CoffeeCup {
this.checkMaterials(orderShot);
console.log("์บก์์ฐ๊ธฐ ์ " + this.capsule);
this.useCapsule(orderShot);
console.log("๋ฌผ์ฐ๊ธฐ ์ " + this.water);
this.useWater();
this.heatWater();
return this.extract(orderShot);
}
protected checkMaterials(orderShot: number) {
if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
throw new Error(`์ปคํผ์บก์ ๋ถ์กฑ!!! ํ์ฌ ๋ณด์ ์บก์ : ${this.capsule}`);
}
if (this.water < CoffeMachine.ONE_CUP_WATER) {
throw new Error(`๋ฌผ ๋ถ์กฑ!!! ๋จ์ ๋ฌผ ${this.water}`);
}
}
clean(): void {
console.log("์ปคํผ๋จธ์ ํ๊ตฌ๋ ์ค!");
}
protected abstract extract(shots: number): CoffeeCup;
private heatWater() {
console.log("๋ฌผ ๋์ด๋ ์ค...");
}
private useCapsule(shot: number) {
console.log("์บก์์ฐ๋ฌ์์ต๋๋ค.");
this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
console.log("์บก์ ์ฐ๊ณ ๋ ํ" + this.capsule);
}
protected useWater() {
console.log("๋ฌผ์ฐ๋ฌ์์ต๋๋ค.");
this.water -= CoffeMachine.ONE_CUP_WATER;
console.log("๋ฌผ์ฐ๊ณ ๋ ํ " + this.water);
}
addCapsule(capsule: number) {
this.capsule += capsule;
}
fulfillWater(water: number) {
this.water += water;
}
get Water(): number {
return this.water;
}
get Capsule(): number {
return this.capsule;
}
}
// CoffeMachine ํด๋์ค๋ฅผ ์์๋ฐ์ CafeLatteMachine ํด๋์ค์ด๋ค.
// tslint:disable-next-line: max-classes-per-file
class CafeLatteMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private milkFrother: CheapMilkSteamer
) {
super(capsule, water);
}
protected extract(shots: number): CoffeeCup {
const blackCoffee = {
orderShot: shots,
};
return this.milkFrother.addMilkform(blackCoffee);
}
}
// CoffeMachine ํด๋์ค ๋ฅผ ์์๋ฐ์ saltCoffeeMachine ํด๋์ค์ด๋ค.
class saltCoffeeMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private saltTopping: SaltMixer
) {
super(capsule, water);
}
protected extract(shots: number): CoffeeCup {
const blackCoffee = {
orderShot: shots,
};
return this.saltTopping.addSalt(blackCoffee);
}
}
const machines: CoffeeMaker[] = [
new CafeLatteMachine(15, 25, new CheapMilkSteamer()),
new saltCoffeeMachine(5, 10, new SaltMixer()),
];
machines.forEach((machine) => {
console.log("------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------");
console.log(machine.makeCoffee(1));
});
<์ถ๋ ฅ ๊ฒฐ๊ณผ> ์ ๋์ํ๋ค.
------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------
์บก์์ฐ๊ธฐ ์ 15
์บก์์ฐ๋ฌ์์ต๋๋ค.
์บก์ ์ฐ๊ณ ๋ ํ12
๋ฌผ์ฐ๊ธฐ ์ 25
๋ฌผ์ฐ๋ฌ์์ต๋๋ค.
๋ฌผ์ฐ๊ณ ๋ ํ 15
๋ฌผ ๋์ด๋ ์ค...
๋ชฝ๊ธ๋ชฝ๊ธ ํฌ์ญํฌ์ญํ ์ฐ์ ํผ
{ orderShot: 1, hasMilk: true }
------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------
์บก์์ฐ๊ธฐ ์ 5
์บก์์ฐ๋ฌ์์ต๋๋ค.
์บก์ ์ฐ๊ณ ๋ ํ2
๋ฌผ์ฐ๊ธฐ ์ 10
๋ฌผ์ฐ๋ฌ์์ต๋๋ค.
๋ฌผ์ฐ๊ณ ๋ ํ 0
๋ฌผ ๋์ด๋ ์ค...
์๊ธ์ ํ๊ผฌ์ง ์ง์๋ค
{ orderShot: 1, hasSalt: true }
์ ๋ฆฌํ์๋ฉด, ์ถ์ํด๋์ค๋ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ์ ์๋ค.
๊ณตํต์ ์ธ ๊ธฐ๋ฅ๋ค์ ๋ค ์ถ์ํด๋์ค ์์์ ๊ตฌํํด์ฃผ๊ณ ,
๋จ ์์๋ฐ์ ์์ํด๋์ค ๋ณ๋ก ๋ฌ๋ผ์ ธ์ผ ํ๋ ๊ธฐ๋ฅ(๋ฉ์๋)๊ฐ ์๋ค๋ฉด,
๊ทธ ๋ถ๋ถ๋ง abstract method๋ก ์ ์ํ ์ ์๋ค.(๊ตฌํx)
์ธํฐํ์ด์ค์์ ํจ์์ ๊ท๊ฒฉ์ ์ ์ํ ๊ฒ ์ฒ๋ผ
์ถ์ํด๋์ค์ abstract method๋ ํจ์์ ์ด๋ฆ์ ๋ฌด์์ด๊ณ ์ด๋ค ๊ฒ๋ค์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์์ผํ๋์ง ์ด๋ค ๊ฒ์ ๋ฆฌํดํด์ผํ๋์ง๋ง ์ ์ํ ์ ์๋ค.
๊ณตํต์ ์ผ๋ก ์ฐ์ด๋ ๊ธฐ๋ฅ๋ค์ ๋ด๋ถ์์๋ง ํ์ํ ๊ฒ์ private๋ก,
์ธ๋ถ์์ ํธ์ถ๋์ผ ํ๋ ๊ธฐ๋ฅ๋ค์ public์ผ๋ก ๋ง๋ค ์ ์๊ณ ,
๊ตฌํํ๋ ํด๋์ค๋ง๋ค ๋ฌ๋ผ์ ธ์ผ ํ๋ abstract method๋ง ์ด๋ฅผ ๊ตฌํํ๋ ์์ ํด๋์ค์์ ๊ตฌํํด์ฃผ๋ฉด ๋๋ค.
(์ถ์ํด๋์ค๋ฅผ ์์๋ฐ์์์๋ ๋ถ๊ตฌํ๊ณ abstract method๋ฅผ ๊ตฌํํ์ง ์์ผ๋ฉด ์๋ฌ๋ฉ์์ง๋ฅผ ๋ฐ๋๋ค)
์ด๋ ๊ฒ ์ถ์ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์กฐ๊ธ ๋ ์์ ํ๊ฒ ํ๋ก๊ทธ๋๋จธ๊ฐ ์๋ํ ๋๋ก ๊ณตํต์ ์ธ ๊ธฐ๋ฅ๋ค์ ์ํํ๊ณ
๋ฌ๋ผ์ ธ์ผ ํ๋ ๊ฒ๋ง ์์ํ๋ ํด๋์ค์๊ฒ ๊ทธ๊ฒ์ ๊ผญ ๊ตฌํํ ๊ฒ์ ๊ฐ์ ํ ์ ์๋ค.
<์ต์ข ์ฝ๋>
// //์ปคํผ๋จธ์ ๋ง๋ค๊ธฐ
type CoffeeCup = {
orderShot: number;
hasMilk?: boolean;
hasSalt?: boolean;
};
interface CoffeeMaker {
makeCoffee(shots: number): CoffeeCup;
}
//์ผ๋ฐ ์ฐ์ ๊ฑฐํ๊ธฐ
class CheapMilkSteamer {
//(1)์ฐ์ ๊ฑฐํ์ ๋ง๋๋ ๋ด๋ถ ํจ์
private steamMilk(): void {
console.log("๋ชฝ๊ธ๋ชฝ๊ธ ํฌ์ญํฌ์ญํ ์ฐ์ ํผ");
}
//(2)๋ง๋ค์ด์ง ์ปคํผ์ปต์ ๋ฐ์์, ๋ง๋ค์ด์ง ์ฐ์ ๊ฑฐํ(1)์ ๋ถ์ด์ ์ด ์ปคํผ์ปต์ ๋ค์ ๋ฆฌํดํ๋ ํจ์
addMilkform(cup: CoffeeCup): CoffeeCup {
this.steamMilk();
return {
...cup,
hasMilk: true,
};
}
}
//์๊ธ๋ฏน์
class SaltMixer {
//(1)์๊ธ์ ์ง๋ ๋ด๋ถ ํจ์
private getSalt() {
console.log("์๊ธ์ ํ๊ผฌ์ง ์ง์๋ค");
return true;
}
//(2)๋ง๋ค์ด์ง ์ปคํผ์ปต์ ๋ฐ์์, ์ง์ ์๊ธ(1)์ ๋ฟ๋ ค์ ์ด ์ปคํผ์ปต์ ๋ค์ ๋ฆฌํดํ๋ ํจ์
addSalt(cup: CoffeeCup): CoffeeCup {
const salt = this.getSalt();
return {
...cup,
hasSalt: salt,
};
}
}
// CoffeeMaker ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ CoffeMachine ํด๋์ค์ด๋ค.////////////////////////////
abstract class CoffeMachine implements CoffeeMaker {
protected static ONE_SHOT_CAPSULE: number = 3;
protected static ONE_CUP_WATER: number = 10;
public constructor(
protected capsule: number = 3,
protected water: number = 10
) {}
makeCoffee(orderShot: number): CoffeeCup {
this.checkMaterials(orderShot);
console.log("์บก์์ฐ๊ธฐ ์ " + this.capsule);
this.useCapsule(orderShot);
console.log("๋ฌผ์ฐ๊ธฐ ์ " + this.water);
this.useWater();
this.heatWater();
return this.extract(orderShot);
}
protected checkMaterials(orderShot: number) {
if (this.capsule < orderShot * CoffeMachine.ONE_SHOT_CAPSULE) {
throw new Error(`์ปคํผ์บก์ ๋ถ์กฑ!!! ํ์ฌ ๋ณด์ ์บก์ : ${this.capsule}`);
}
if (this.water < CoffeMachine.ONE_CUP_WATER) {
throw new Error(`๋ฌผ ๋ถ์กฑ!!! ๋จ์ ๋ฌผ ${this.water}`);
}
}
clean(): void {
console.log("์ปคํผ๋จธ์ ํ๊ตฌ๋ ์ค!");
}
protected abstract extract(shots: number): CoffeeCup;
private heatWater() {
console.log("๋ฌผ ๋์ด๋ ์ค...");
}
private useCapsule(shot: number) {
console.log("์บก์์ฐ๋ฌ์์ต๋๋ค.");
this.capsule -= shot * CoffeMachine.ONE_SHOT_CAPSULE;
console.log("์บก์ ์ฐ๊ณ ๋ ํ" + this.capsule);
}
protected useWater() {
console.log("๋ฌผ์ฐ๋ฌ์์ต๋๋ค.");
this.water -= CoffeMachine.ONE_CUP_WATER;
console.log("๋ฌผ์ฐ๊ณ ๋ ํ " + this.water);
}
addCapsule(capsule: number) {
this.capsule += capsule;
}
fulfillWater(water: number) {
this.water += water;
}
get Water(): number {
return this.water;
}
get Capsule(): number {
return this.capsule;
}
}
// CoffeMachine ํด๋์ค๋ฅผ ์์๋ฐ์ CafeLatteMachine ํด๋์ค์ด๋ค.
// tslint:disable-next-line: max-classes-per-file
class CafeLatteMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private milkFrother: CheapMilkSteamer
) {
super(capsule, water);
}
protected extract(shots: number): CoffeeCup {
const blackCoffee = {
orderShot: shots,
};
return this.milkFrother.addMilkform(blackCoffee);
}
}
// CoffeMachine ํด๋์ค ๋ฅผ ์์๋ฐ์ saltCoffeeMachine ํด๋์ค์ด๋ค.
class saltCoffeeMachine extends CoffeMachine {
public constructor(
protected capsule: number = 3,
protected water: number = 10,
private saltTopping: SaltMixer
) {
super(capsule, water);
}
protected extract(shots: number): CoffeeCup {
const blackCoffee = {
orderShot: shots,
};
return this.saltTopping.addSalt(blackCoffee);
}
}
const machines: CoffeeMaker[] = [
new CafeLatteMachine(15, 25, new CheapMilkSteamer()),
new saltCoffeeMachine(5, 10, new SaltMixer()),
];
machines.forEach((machine) => {
console.log("------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------");
console.log(machine.makeCoffee(1));
});
<์ถ๋ ฅ ๊ฒฐ๊ณผ>
------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------
์บก์์ฐ๊ธฐ ์ 15
์บก์์ฐ๋ฌ์์ต๋๋ค.
์บก์ ์ฐ๊ณ ๋ ํ12
๋ฌผ์ฐ๊ธฐ ์ 25
๋ฌผ์ฐ๋ฌ์์ต๋๋ค.
๋ฌผ์ฐ๊ณ ๋ ํ 15
๋ฌผ ๋์ด๋ ์ค...
๋ชฝ๊ธ๋ชฝ๊ธ ํฌ์ญํฌ์ญํ ์ฐ์ ํผ
{ orderShot: 1, hasMilk: true }
------------์ปคํผ๋จธ์ ๊ฐ๋~!-- ----------
์บก์์ฐ๊ธฐ ์ 5
์บก์์ฐ๋ฌ์์ต๋๋ค.
์บก์ ์ฐ๊ณ ๋ ํ2
๋ฌผ์ฐ๊ธฐ ์ 10
๋ฌผ์ฐ๋ฌ์์ต๋๋ค.
๋ฌผ์ฐ๊ณ ๋ ํ 0
๋ฌผ ๋์ด๋ ์ค...
์๊ธ์ ํ๊ผฌ์ง ์ง์๋ค
{ orderShot: 1, hasSalt: true }