π μν ν¨ν΄μ΄λ?
μν ν¨ν΄(State Pattern)μ κ°μ²΄μ λ΄λΆ μνκ° λ³κ²½λ λ κ°μ²΄μ νλμ λ³κ²½ν μ μκ² νλ νμ λμμΈ ν¨ν΄μ λλ€. μ΄ ν¨ν΄μ μ¬μ©νλ©΄ κ°μ²΄κ° λ§μΉ ν΄λμ€λ₯Ό λ°κΎΌ κ²μ²λΌ 보μ΄κ² ν μ μμ΅λλ€.
μν ν¨ν΄μ μν λ¨Έμ (State Machine)μ κ°λ μ κ°μ²΄ μ§ν₯ λ°©μμΌλ‘ ꡬνν κ²μΌλ‘, 볡μ‘ν 쑰건문μ μ κ±°νκ³ κ° μνλ³ νλμ λ 립μ μΈ ν΄λμ€λ‘ μΊ‘μνν©λλ€.
ποΈ μν ν¨ν΄μ ν΅μ¬ κ΅¬μ± μμ
1. π Context (컨ν μ€νΈ)
- νμ¬ μνλ₯Ό μ°Έμ‘°νλ ν΄λμ€
- ν΄λΌμ΄μΈνΈκ° μ§μ μνΈμμ©νλ μΈν°νμ΄μ€λ₯Ό μ 곡
- μν λ³κ²½ μμ²μ νμ¬ μν κ°μ²΄μ μμ
2. π― State (μν μΈν°νμ΄μ€)
- λͺ¨λ ꡬ체μ μΈ μν ν΄λμ€κ° ꡬνν΄μΌ νλ μΈν°νμ΄μ€
- μνλ³λ‘ λ€λ₯΄κ² μ²λ¦¬λ λ©μλλ€μ μ μ
3. π§ ConcreteState (ꡬ체μ μΈ μν)
- State μΈν°νμ΄μ€λ₯Ό ꡬννλ ν΄λμ€λ€
- κ° μνμμμ ꡬ체μ μΈ νλμ μ μ
- λ€μ μνλ‘μ μ ν λ‘μ§μ ν¬ν¨ν μ μμ
β¨ μν ν¨ν΄μ μ¬μ©νλ μ΄μ
π μ₯μ
- 볡μ‘ν 쑰건문 μ κ±°: κ±°λν if-else λ¬Έμ΄λ switch λ¬Έμ μ κ±°ν μ μμ΅λλ€
- λ¨μΌ μ± μ μμΉ: κ° μνλ³ μ½λλ₯Ό λ³λ ν΄λμ€λ‘ λΆλ¦¬ν©λλ€
- κ°λ°©-νμ μμΉ: μλ‘μ΄ μν μΆκ° μ κΈ°μ‘΄ μ½λ μμ μμ΄ νμ₯ κ°λ₯ν©λλ€
- μ μ§λ³΄μμ± ν₯μ: μνλ³ λ‘μ§μ΄ λͺ ννκ² λΆλ¦¬λμ΄ μ΄ν΄νκΈ° μ½μ΅λλ€
π λ¨μ
- ν΄λμ€ μ μ¦κ°: μνλ§λ€ λ³λμ ν΄λμ€λ₯Ό μμ±ν΄μΌ ν©λλ€
- 볡μ‘λ μ¦κ°: κ°λ¨ν μν λ³νμ κ²½μ° μ€λ²μμ§λμ΄λ§μ΄ λ μ μμ΅λλ€
π Java μμ : μλμ°¨ μν κ΄λ¦¬
μλμ°¨μ μν(μ μ§, μ£Όν, μ£Όμ°¨)μ λ°λΌ λ€λ₯Έ νλμ νλ μμ μ λλ€.
μν μΈν°νμ΄μ€ μ μ
// μλμ°¨ μν μΈν°νμ΄μ€
public interface CarState {
void start(Car car);
void drive(Car car);
void park(Car car);
void stop(Car car);
String getStateName();
}
ꡬ체μ μΈ μν ν΄λμ€λ€
// μ μ§ μν
public class StoppedState implements CarState {
@Override
public void start(Car car) {
System.out.println("π μμ§μ μλν©λλ€.");
car.setState(new DrivingState());
}
@Override
public void drive(Car car) {
System.out.println("β λ¨Όμ μλμ κ±Έμ΄μ£ΌμΈμ.");
}
@Override
public void park(Car car) {
System.out.println("β μ΄λ―Έ μ μ§λ μνμ
λλ€.");
}
@Override
public void stop(Car car) {
System.out.println("β μ΄λ―Έ μ μ§λ μνμ
λλ€.");
}
@Override
public String getStateName() {
return "μ μ§";
}
}
// μ£Όν μν
public class DrivingState implements CarState {
@Override
public void start(Car car) {
System.out.println("β μ΄λ―Έ μλμ΄ κ±Έλ €μμ΅λλ€.");
}
@Override
public void drive(Car car) {
System.out.println("πβοΈ λ¬λ¦¬κ³ μμ΅λλ€! λΆλ¦λΆλ¦~");
}
@Override
public void park(Car car) {
System.out.println("π
ΏοΈ μ£Όμ°¨ν©λλ€.");
car.setState(new ParkedState());
}
@Override
public void stop(Car car) {
System.out.println("π μ°¨λ₯Ό λ©μΆ₯λλ€.");
car.setState(new StoppedState());
}
@Override
public String getStateName() {
return "μ£Όν";
}
}
// μ£Όμ°¨ μν
public class ParkedState implements CarState {
@Override
public void start(Car car) {
System.out.println("π μ£Όμ°¨μμ μΆλ°ν©λλ€.");
car.setState(new DrivingState());
}
@Override
public void drive(Car car) {
System.out.println("β λ¨Όμ μ£Όμ°¨μμ λκ°μ£ΌμΈμ.");
}
@Override
public void park(Car car) {
System.out.println("β μ΄λ―Έ μ£Όμ°¨λ μνμ
λλ€.");
}
@Override
public void stop(Car car) {
System.out.println("π μμ§μ λλλ€.");
car.setState(new StoppedState());
}
@Override
public String getStateName() {
return "μ£Όμ°¨";
}
}
컨ν μ€νΈ ν΄λμ€ (μλμ°¨)
// μλμ°¨ 컨ν
μ€νΈ ν΄λμ€
public class Car {
private CarState currentState;
public Car() {
this.currentState = new StoppedState();
}
public void setState(CarState state) {
this.currentState = state;
System.out.println("π μν λ³κ²½: " + state.getStateName());
}
public void start() {
currentState.start(this);
}
public void drive() {
currentState.drive(this);
}
public void park() {
currentState.park(this);
}
public void stop() {
currentState.stop(this);
}
public String getCurrentState() {
return currentState.getStateName();
}
}
μ¬μ© μμ
public class CarStateExample {
public static void main(String[] args) {
Car car = new Car();
System.out.println("=== μλμ°¨ μν ν¨ν΄ ν
μ€νΈ ===");
System.out.println("νμ¬ μν: " + car.getCurrentState());
// μ μ§ μνμμ μμ
car.drive(); // μλμ λ¨Όμ κ±Έμ΄μΌ ν¨
car.start(); // μλ κ±ΈκΈ°
car.drive(); // μ£Όν
car.park(); // μ£Όμ°¨
car.drive(); // μ£Όμ°¨ μνμμ μ΄μ μλ
car.stop(); // μμ§ λκΈ°
}
}
π TypeScript μμ : μ€λ§νΈ ν μμ€ν
μ§μ μν(μΌλ° λͺ¨λ, μΈμΆ λͺ¨λ, μ·¨μΉ¨ λͺ¨λ)μ λ°λΌ λ€λ₯Έ νλμ νλ μμ μ λλ€.
μν μΈν°νμ΄μ€ μ μ
// μ§ μν μΈν°νμ΄μ€
interface HomeState {
enterHome(home: SmartHome): void;
leaveHome(home: SmartHome): void;
goToBed(home: SmartHome): void;
wakeUp(home: SmartHome): void;
getStateName(): string;
}
ꡬ체μ μΈ μν ν΄λμ€λ€
// μΌλ° λͺ¨λ (μ§μ μλ μν)
class HomeMode implements HomeState {
enterHome(home: SmartHome): void {
console.log('β μ΄λ―Έ μ§μ μμ΅λλ€.');
}
leaveHome(home: SmartHome): void {
console.log('πͺ μΈμΆν©λλ€. 보μ λͺ¨λλ₯Ό νμ±νν©λλ€.');
console.log('π‘ λͺ¨λ λΆμ λλλ€.');
console.log('π λ¬Έμ μ κΈλλ€.');
home.setState(new AwayMode());
}
goToBed(home: SmartHome): void {
console.log('π μ·¨μΉ¨ λͺ¨λλ‘ μ νν©λλ€.');
console.log('π‘ μ‘°λͺ
μ μ΄λ‘κ² μ‘°μ ν©λλ€.');
console.log('π μλ¦Όμμ 무μμΌλ‘ μ€μ ν©λλ€.');
console.log('π‘οΈ μ¨λλ₯Ό μλ©΄μ μ ν©νκ² μ‘°μ ν©λλ€.');
home.setState(new SleepMode());
}
wakeUp(home: SmartHome): void {
console.log('β μ΄λ―Έ κΉ¨μ΄μλ μνμ
λλ€.');
}
getStateName(): string {
return 'μΌλ° λͺ¨λ';
}
}
// μΈμΆ λͺ¨λ
class AwayMode implements HomeState {
enterHome(home: SmartHome): void {
console.log('π μ§μ λμμμ΅λλ€. νμν©λλ€!');
console.log('π‘ νκ΄λ±μ μΌλλ€.');
console.log('π λ¬Έμ μ΄κ³ 보μ λͺ¨λλ₯Ό ν΄μ ν©λλ€.');
console.log('π‘οΈ μ¨λλ₯Ό μΎμ νκ² μ‘°μ ν©λλ€.');
home.setState(new HomeMode());
}
leaveHome(home: SmartHome): void {
console.log('β μ΄λ―Έ μΈμΆ μ€μ
λλ€.');
}
goToBed(home: SmartHome): void {
console.log('β μ§μ μμ§ μμ΅λλ€. λ¨Όμ μ§μ λ€μ΄μμ£ΌμΈμ.');
}
wakeUp(home: SmartHome): void {
console.log('β μ§μ μμ§ μμ΅λλ€.');
}
getStateName(): string {
return 'μΈμΆ λͺ¨λ';
}
}
// μ·¨μΉ¨ λͺ¨λ
class SleepMode implements HomeState {
enterHome(home: SmartHome): void {
console.log('β μ΄λ―Έ μ§μ μμ΅λλ€.');
}
leaveHome(home: SmartHome): void {
console.log('π
κΈ°μ ν μΈμΆν©λλ€.');
console.log('π‘ λͺ¨λ λΆμ λλλ€.');
console.log('π λ¬Έμ μ κ·Έκ³ λ³΄μ λͺ¨λλ₯Ό νμ±νν©λλ€.');
home.setState(new AwayMode());
}
goToBed(home: SmartHome): void {
console.log('β μ΄λ―Έ μ·¨μΉ¨ λͺ¨λμ
λλ€.');
}
wakeUp(home: SmartHome): void {
console.log('βοΈ μ’μ μμΉ¨μ
λλ€! κΈ°μ λͺ¨λλ‘ μ νν©λλ€.');
console.log('π‘ μ‘°λͺ
μ λ°κ² μ‘°μ ν©λλ€.');
console.log('π μλ¦Όμμ νμ±νν©λλ€.');
console.log('β μ»€νΌ λ¨Έμ μ μ€λΉν©λλ€.');
home.setState(new HomeMode());
}
getStateName(): string {
return 'μ·¨μΉ¨ λͺ¨λ';
}
}
컨ν μ€νΈ ν΄λμ€ (μ€λ§νΈ ν)
// μ€λ§νΈ ν 컨ν
μ€νΈ ν΄λμ€
class SmartHome {
private currentState: HomeState;
constructor() {
this.currentState = new HomeMode();
}
setState(state: HomeState): void {
this.currentState = state;
console.log(`π μν λ³κ²½: ${state.getStateName()}`);
}
enterHome(): void {
this.currentState.enterHome(this);
}
leaveHome(): void {
this.currentState.leaveHome(this);
}
goToBed(): void {
this.currentState.goToBed(this);
}
wakeUp(): void {
this.currentState.wakeUp(this);
}
getCurrentState(): string {
return this.currentState.getStateName();
}
}
μ¬μ© μμ
// μ€λ§νΈ ν ν
μ€νΈ
function testSmartHome(): void {
const home = new SmartHome();
console.log('=== μ€λ§νΈ ν μν ν¨ν΄ ν
μ€νΈ ===');
console.log(`νμ¬ μν: ${home.getCurrentState()}`);
// μΌλ° λͺ¨λμμ μμ
home.goToBed(); // μ·¨μΉ¨ λͺ¨λλ‘ μ ν
home.leaveHome(); // μ·¨μΉ¨ μ€μ μΈμΆ μλ
home.wakeUp(); // κΈ°μ
home.leaveHome(); // μΈμΆ
home.goToBed(); // μΈμΆ μ€μ μ·¨μΉ¨ μλ
home.enterHome(); // κ·κ°
home.goToBed(); // λ€μ μ·¨μΉ¨
}
// ν
μ€νΈ μ€ν
testSmartHome();
π€ μν ν¨ν΄ vs μ λ΅ ν¨ν΄
λ§μ κ°λ°μλ€μ΄ μν ν¨ν΄κ³Ό μ λ΅ ν¨ν΄μ νΌλνλλ°, λ ν¨ν΄μ μ°¨μ΄μ μ λ€μκ³Ό κ°μ΅λλ€:
μν ν¨ν΄ (State Pattern)
- λͺ©μ : κ°μ²΄μ λ΄λΆ μνμ λ°λΌ νλμ λ³κ²½
- μν μ ν: μν κ°μ²΄ μ€μ€λ‘κ° λ€μ μνλ₯Ό κ²°μ
- μμ‘΄μ±: μνλ€μ΄ μλ‘λ₯Ό μκ³ μμ
- μ¬μ© μμ : μν λ¨Έμ , κ²μ μΊλ¦ν°, UI μ»΄ν¬λνΈ λ±
μ λ΅ ν¨ν΄ (Strategy Pattern)
- λͺ©μ : μκ³ λ¦¬μ¦μ λ°νμμ μ ν
- μ λ΅ μ ν: ν΄λΌμ΄μΈνΈκ° μ λ΅μ μ ν
- μμ‘΄μ±: μ λ΅λ€μ΄ μλ‘λ₯Ό λͺ¨λ¦
- μ¬μ© μμ : μ λ ¬ μκ³ λ¦¬μ¦, κ²°μ λ°©μ, μμΆ λ°©μ λ±
π― μΈμ μν ν¨ν΄μ μ¬μ©ν΄μΌ ν κΉ?
μν ν¨ν΄μ λ€μκ³Ό κ°μ μν©μμ μ μ©ν©λλ€:
- 볡μ‘ν μ‘°κ±΄λ¬Έμ΄ λ§μ κ²½μ°: κ°μ²΄μ μνμ λ°λΌ λ€λ₯Έ νλμ νλ κ±°λν if-else λ¬Έμ΄ μμ λ
- μν μ νμ΄ λ³΅μ‘ν κ²½μ°: μ¬λ¬ μν κ°μ μ ν κ·μΉμ΄ 볡μ‘ν λ
- μνλ³ νλμ΄ λͺ νν ꡬλΆλλ κ²½μ°: κ° μνμμ μμ ν λ€λ₯Έ νλμ ν΄μΌ ν λ
- μνκ° μμ£Ό μΆκ°λκ±°λ λ³κ²½λλ κ²½μ°: μλ‘μ΄ μνλ₯Ό μ½κ² μΆκ°νκ³ μΆμ λ
π κ²°λ‘
μν ν¨ν΄μ 볡μ‘ν μν κ΄λ¦¬ λ‘μ§μ κΉλνκ² μ 리ν μ μλ κ°λ ₯ν λμμΈ ν¨ν΄μ λλ€. νΉν μν λ¨Έμ μ΄ νμν μμ€ν μμλ νμμ μΈ ν¨ν΄μ΄λΌκ³ ν μ μμ΅λλ€.
νμ§λ§ κ°λ¨ν μν λ³νμ κ²½μ°μλ μ€νλ € 볡μ‘λλ§ μ¦κ°μν¬ μ μμΌλ―λ‘, νλ‘μ νΈμ μꡬμ¬νκ³Ό 볡μ‘λλ₯Ό κ³ λ €νμ¬ μ μ€νκ² μ μ©ν΄μΌ ν©λλ€.
μν ν¨ν΄μ μ νμ©νλ©΄ μ μ§λ³΄μκ° μ½κ³ νμ₯ κ°λ₯ν μ½λλ₯Ό μμ±ν μ μμ΅λλ€! π
λκΈ