μν ν¨ν΄(State Pattern)μ μ¬μ©ν΄λ³΄μ
π₯° π π π© π€¬ π΄
μν(νμ¬ μ§νμ€μΈ νμ)λ₯Ό λνλ΄κΈ° μν΄ μ΄λ€ λ°©μμ μ¬μ©ν΄ μλκ°?
Enum
μ΄κ±°ν(Enum) μ΄λ μλ‘ μ°κ΄λ μμλ€μ μ§ν©μ΄λ€. μνλ₯Ό λνλ΄κΈ°μλ μ λ§ νΈλ¦¬ν λ°©μμ΄λΌκ³ μκ°νλ€. νμ§λ§ Enum μ κ°μ²΄ μ§ν₯μ μΈ νλ‘κ·Έλλ°μ΄λΌκ³ νκΈ° μ 맀ν λΆλΆμ΄ μλ€. κ·Έ λΆλΆμ λν΄μλ μ‘°κΈ μλ€κ° μμ보μ.
μν ν¨ν΄
βνΉμ κΈ°λ₯μ μνν ν λ€μ μνλ₯Ό λ°ννλ κ²β
μν ν¨ν΄μ μνκ° λ§μμ§λλΌλ μ½λμ 볡μ‘λκ° μ¦κ°νμ§ μμ§λ§ enum μμ 쑰건문μ μ΄μ©ν λ°©μμ μ½λλ₯Ό 볡μ‘νκ² λ§λ€μ΄ μ μ§ λ³΄μλ₯Ό μ΄λ ΅κ² νλ€.
μν ν¨ν΄ μ μ©
λμΌν λ©μλκ° μνμ λ°λΌ λ€λ₯΄κ² λμν λ μ¬μ©ν μ μλ ν¨ν΄μ΄ μν ν¨ν΄(State Pattern)μ΄λ€. μν ν¨ν΄μμλ μνλ₯Ό λ³λμ νμ μΌλ‘ λΆλ¦¬νκ³ μνλ³λ‘ μλ§μ νμ νμ μ ꡬννλ€. μν ν¨ν΄μ λν΄ μκ² λμμΌλ μ€μ λ‘ μν ν¨ν΄μ μ¬μ©ν΄λ³΄μ.
λ°±κ²¬μ΄ λΆμ¬μΌν(ηΎθ¦θ δΈε¦δΈθ‘)
μνν¨ν΄μ μ¬μ©ν΄λ³΄κΈ° μν κ°λ¨ν μμ νλ‘κ·Έλ¨μ λ§λ€μ΄ λ³Έλ€. μμμ μ¬μ©λ νλ‘κ·Έλ¨μ μ¬λμ κ°μ μνλ₯Ό λ³κ²½νλ κ°λ¨ν μμ νλ‘κ·Έλ¨μ΄λ€.
ꡬνν μ μλ κΈ°λ₯μ λν μμλ₯Ό μ£ΌμμΌλ‘ μ μλ€. μν ν¨ν΄μ μΆμνλ λμΌν λ©μλμ μνλ§λ€ λ€λ₯Έ νΉμ κΈ°λ₯μ μνν ν λ€μ μνλ₯Ό λ°ννλ κ²μ΄ μν ν¨ν΄μ ν΅μ¬μ΄λΌκ³ λ³Ό μ μλ€.
@Override
public State μ΄λ€_νμ() {
νμ¬ μνμ λν΄μ μ΄λ€ νμκ° λ°μνμ λμ μν©μ μ²λ¦¬νλ€.
μ²λ¦¬κ° λλ ν λ³νλ μνλ₯Ό λ°ννλ€.
}
State Interface
ꡬνν μνμ λ³νλ₯Ό μ€ κΈ°λ₯μ μΆμννλ€. ν΄λΉ κΈ°λ₯μ λ¨μνκ² λ‘λ λΉμ²¨μ΄ λμμ λ, λμ λ²μμ λ, λμ μμμ λ, λΉμ²¨λ λ‘λλ₯Ό μμ΄λ²λ Έμ λλ₯Ό μΆμνν΄λκ³ μνμ λ§κ² ꡬννλλ‘ λμ΄ μλ€.
public interface State {
State winLottery();
State earnMoney();
State loseMoney();
State loseWinLottery();
void printCurrentEmotion();
}
Emotion
λ‘λκ° λΉμ²¨λκ±°λ λΉμ²¨λ λ‘λλ₯Ό μμ΄λ²λ¦° κ²½μ°λ μ΄λ ν μνμμλ μ΅μμ κΈ°λΆκ³Ό μ΅μ μ κΈ°λΆμ μνλ‘ λ³κ²½μν¨λ€κ³ μκ°νκ³ , μ€λ³΅λλ κΈ°λ₯μ΄λ―λ‘ μΆμ ν΄λμ€λ‘ ꡬννλ€. μ΄λ κ² λ§λ€μ΄μ§ μΆμ ν΄λμ€λ₯Ό μμλ°μ κ°κ°μ μνλ₯Ό ꡬννλ€. μ΄νμ μμ ν λμ λ°λΌ κΈ°λΆμ΄ λ¬λΌμ§λ κΈ°λ₯μ²λΌ μνκ° νμν κ²½μ° ν΄λΉ μΆμ ν΄λμ€μ μνλ₯Ό μΆκ°νμ¬ κ΅¬νν μ μκ² λ€.
public abstract class Emotion implements State {
@Override // λ‘λ λΉμ²¨μ κΈ°λΆμ΄ μ΅μμ΄ λ©λλ€.
public State winLottery() {
return new Perfect();
}
@Override // λΉμ²¨λ λ‘λλ₯Ό μμ΄λ²λ¦¬λ©΄ κΈ°λΆμ΄ μ΅μ
μ΄ λ©λλ€.
public State loseWinLottery() {
return new Terrible();
}
}
Perfect
μ΅μμ κΈ°λΆ μνλ₯Ό νννλ ν΄λμ€λ₯Ό λ§λ λ€.
public class Perfect extends Emotion {
@Override // κΈ°λΆμ΄ λ³κ²½λμ§ μμ΅λλ€.
public State earnMoney() {
// κΈ°λΆμ΄ λ μ’μμ§ μ μκΈ° λλ¬Έμ μμΈλ₯Ό λ°μμν€λ λ°©μμ μ¬μ©ν μλ μλ€.
return this;
}
@Override // λμ μμ΄μ ν λ¨κ³ κΈ°λΆμ΄ λλΉ μ§λλ€.
public State loseMoney() {
return new Happy();
}
@Override
public void printCurrentEmotion() {
System.out.println("μ΅κ³ μ
λλ€.");
}
}
Happy
κΈ°λΆμ΄ μ’μ μνλ₯Ό νννλ ν΄λμ€λ₯Ό λ§λ λ€.
public class Happy extends Emotion {
@Override // λμ λ²μ΄μ ν λ¨κ³ κΈ°λΆμ΄ μ’μμ§λλ€.
public State earnMoney() {
// μ) κΈ°λΆμ΄ λ무 μ’μμ μ£Όλ³ μ§μΈλ€κ³Ό νν°λ₯Ό νλ κΈ°λ₯ μ²λ¦¬
return new Perfect();
}
@Override // λμ μμ΄μ ν λ¨κ³ κΈ°λΆμ΄ λλΉ μ§λλ€.
public State loseMoney() {
return new SoSo();
}
@Override
public void printCurrentEmotion() {
System.out.println("ν볡ν©λλ€.");
}
}
SoSo
λ³΄ν΅ κΈ°λΆ μνλ₯Ό νννλ ν΄λμ€λ₯Ό λ§λ λ€.
public class SoSo extends Emotion {
@Override // λμ λ²μ΄μ ν λ¨κ³ κΈ°λΆμ΄ μ’μμ§λλ€.
public State earnMoney() {
return new Happy();
}
@Override // λμ μμ΄μ ν λ¨κ³ κΈ°λΆμ΄ λλΉ μ§λλ€.
public State loseMoney() {
return new Bad();
}
@Override
public void printCurrentEmotion() {
System.out.println("κ·Έμ κ·Έλμ.");
}
}
Bad
λμ κΈ°λΆ μνλ₯Ό νννλ ν΄λμ€λ₯Ό λ§λ λ€.
public class Bad extends Emotion {
@Override // λμ λ²μ΄μ ν λ¨κ³ κΈ°λΆμ΄ μ’μμ§λλ€.
public State earnMoney() {
return new SoSo();
}
@Override // λμ μμ΄μ ν λ¨κ³ κΈ°λΆμ΄ λλΉ μ§λλ€.
public State loseMoney() {
// μ) κΈ°λΆμ΄ λ무 λλΉ μ§λ©° μΉν μΉκ΅¬μ μ μ λ¨Ήλ κΈ°λ₯ μ²λ¦¬
return new Terrible();
}
@Override
public void printCurrentEmotion() {
System.out.println("λ³λ‘μ
λλ€.");
}
}
Terrible
μ΅μ μ κΈ°λΆ μνλ₯Ό νννλ ν΄λμ€λ₯Ό λ§λ λ€.
public class Terrible extends Emotion {
@Override // λμ λ²μ΄μ ν λ¨κ³ κΈ°λΆμ΄ μ’μμ§λλ€.
public State earnMoney() {
return new Bad();
}
@Override // κΈ°λΆμ΄ λ³κ²½λμ§ μμ΅λλ€.
public State loseMoney() {
// κΈ°λΆμ΄ λ λλΉ μ§ μ μκΈ° λλ¬Έμ μμΈλ₯Ό λ°μμν€λ λ°©μμ μ¬μ©ν μλ μλ€.
return this;
}
@Override
public void printCurrentEmotion() {
System.out.println("μ΅μ
μ
λλ€.");
}
}
κΈ°λ₯ μ μ©
Person
μμμ ν μ€νΈκ° μ μμ μΌλ‘ ν΅κ³Όλμλ€λ©΄ μ€μ λ‘ μ ν리μΌμ΄μ μμ μ€νν΄ λ³΄λλ‘ νμ. λ§λ€μ΄λ κ°μ μνλ₯Ό κ°μ§κ³ μλ Person μ λ§λ λ€. Person μμ ꡬνν κΈ°λ₯λ€μ νΈμΆμ΄ λλ©΄ μνκ° λ³κ²½λκ³ λ³κ²½λ μνλ₯Ό μΆλ ₯ν΄μ£Όλ κ°λ¨ν κΈ°λ₯μ΄ κ΅¬νλμ΄μλ€.
public class Person {
private State state;
public Person(State state) {
this.state = state;
}
public void winLottery() {
state = state.winLottery();
state.printCurrentEmotion();
}
public void earnMoney() {
state = state.earnMoney();
state.printCurrentEmotion();
}
public void loseMoney() {
state = state.loseMoney();
state.printCurrentEmotion();
}
public void printCurrentEmotion() {
state.printCurrentEmotion();
}
}
Application
Person μΈμ€ν΄μ€λ₯Ό μμ±νλ€. λ©μλ νΈμΆμ λ°λΌμ μνκ° λ³κ²½λλ λͺ¨μ΅μ νμΈν μ μλ€. μ΄λ κ² μνλ₯Ό κ°μ²΄λ‘ κ΄λ¦¬νκ² λλ©΄ κ°κ°μ μνλ§λ€ μΈλΆμ μΈ κΈ°λ₯ ꡬνμ ν μ μλ€.
public class Application {
public static void main(String[] args) {
Person person = new Person(new SoSo());
person.printCurrentEmotion();
person.earnMoney();
person.winLottery();
person.loseMoney();
person.loseMoney();
person.loseMoney();
person.loseMoney();
}
}
/* μ€ν κ²°κ³Ό
> Task :Application.main()
κ·Έμ κ·Έλμ.
ν볡 ν©λλ€.
μ΅κ³ μ
λλ€.
ν볡 ν©λλ€.
κ·Έμ κ·Έλμ.
λ³λ‘ μ
λλ€.
μ΅μ
μ
λλ€. */
μλ‘μ΄ κ°μ μνκ° μΆκ°λλ€λ©΄?
μμ λ³νμλ ν¬κ² κ°μ λ³νκ° μκΈ°μ§ μλ μνμΈ Sleepy λΌλ κ°μ μνκ° μΆκ°λλ€κ³ νλ€.
Sleepy
public class Sleepy extends Emotion {
@Override // μ‘Έλ¦° μνμμλ λμ μ‘°κΈ μ»λλ€κ³ ν΄μ κΈ°λΆμ΄ λ¬λΌμ§μ§ μλλ€.
public State earnMoney() {
return this;
}
@Override // μ‘Έλ¦° μνμμλ λμ μ‘°κΈ μλλ€κ³ ν΄μ κΈ°λΆμ΄ λ¬λΌμ§μ§ μλλ€.
public State loseMoney() {
return this;
}
@Override
public void printCurrentEmotion() {
System.out.println("쑸립λλ€.");
}
}
μμ κ°μ μλ‘μ΄ μνκ° μΆκ°λλλΌλ μ½ν μ€νΈ μ½λκ° λ°λ μν₯μ μ΅μνλλ€.
public class Application {
public static void main(String[] args) {
Person person = new Person(new Sleepy());
person.printCurrentEmotion(); // state = Sleepy.class
person.earnMoney(); // state = Sleepy.class
person.winLottery(); // state = Perfect.class
}
}
κ²½νν΄ λ³΄μλκ°?
μ΄λ€κ°? κ°λ¨ν μμλ₯Ό λ€μ΄μ μνν¨ν΄μ λ ν΄μ μ€λͺ μ νλ€.
μνν¨ν΄μ΄λ κ°μ²΄ μ§ν₯ λ°©μμΌλ‘ μν κΈ°κ³(ν λ²μ μ€λ‘μ§ νλμ μνλ§μ κ°μ§κ² λλ©°, νμ¬ μν(Current State)λ μμμ μ£Όμ΄μ§ μκ°μ μνλ₯Ό μΉν¨)λ₯Ό ꡬννλ νμ μννΈμ¨μ΄ λμμΈ ν¨ν΄μ΄λ€. μν ν¨ν΄μ μ΄μ©νλ©΄ μν ν¨ν΄ μΈν°νμ΄μ€μ νμ ν΄λμ€λ‘μ κ°κ°μ μνλ₯Ό ꡬνν¨μΌλ‘μ¨, λ ν¨ν΄μ λΆλͺ¨ν΄λμ€μ μν΄ μ μλλ λ©μλλ₯Ό νΈμΆνμ¬ μν λ³νλ₯Ό ꡬνν¨μΌλ‘μ¨ μν κΈ°κ³λ₯Ό ꡬννλ€. μν ν¨ν΄μ μ₯μ μ μλ‘μ΄ μνκ° μΆκ°λλλΌλ μ½ν μ€νΈ μ½λκ° λ°λ μν₯μ μ΅μνλλ€. ν΄λμ€λ₯Ό μΆκ°νλλΌλ κΈ°μ‘΄μ λ©μλμ μ½λλ κ·Έλλ‘ μ μ§λλ€. λν μνμ λ°λ₯Έ λμμ ꡬνν μ½λκ° μνλ³λ‘ ꡬλΆλκΈ° λλ¬Έμ μνλ³ λμμ μμ νκΈ° μ½λ€.
λμ± λ³΅μ‘ν λ‘μ§μ΄ μΆκ° λλ€λ©΄ μν ν¨ν΄μ λ ν° λΉμ λ³Ό κ²μ΄λ€. κ·Έλ¦¬κ³ κΆκΈν΄ ν μ μκΈ° λλ¬Έμ κ°μ κΈ°λ₯μ νλ enum μνλ₯Ό ꡬνν΄ λ³΄μλ€.
Enum
public enum State {
PERFECT("μ΅κ³ μ
λλ€."),
HAPPY("ν볡 ν©λλ€"),
SO_SO("κ·Έμ κ·Έλμ."),
BAD("λ³λ‘ μ
λλ€."),
TERRIBLE("μ΅μ
μ
λλ€.");
private String message;
State(String message) {
this.message = message;
}
public State winLottery() {
return PERFECT;
}
// if (else if) 쑰건 λΆκΈ°λ‘ μνλ₯Ό μ²λ¦¬νλ€.
public State earnMoney() {
if (this == TERRIBLE) {
return BAD;
}
if (this == BAD) {
return SO_SO;
}
if (this == SO_SO) {
return HAPPY;
}
return PERFECT;
}
// μμ λ§μ°¬κ°μ§λ‘ switch 쑰건 λΆκΈ°λ‘ μνλ₯Ό μ²λ¦¬νλ€.
public State loseMoney() {
switch (this) {
case PERFECT:
return HAPPY;
case HAPPY:
return SO_SO;
case SO_SO:
return BAD;
default:
return TERRIBLE;
}
}
public State loseLottery() {
return TERRIBLE;
}
public void printCurrentEmotion() {
System.out.println(message);
}
}
μμ μμμ²λΌ Sleep μ΄λΌλ μνλ₯Ό μΆκ° νλ€λ©΄ enum μ earnMoney() μ loseMoney() λ₯Ό μμ ν΄μΌ νλ€.
SLEEP("쑸립λλ€.");
public State earnMoney() {
if (this == TERRIBLE) {
return BAD;
}
if (this == BAD) {
return SO_SO;
}
if (this == SO_SO) {
return HAPPY;
}
if (this == HAPPY) {
return PERFECT;
}
default:
return SLEEP;
}
}
public State loseMoney() {
switch (this) {
case PERFECT:
return HAPPY;
case HAPPY:
return SO_SO;
case SO_SO:
return BAD;
case BAD:
return TERRIBLE;
default:
return SLEEP;
}
}
enum νλμμ λͺ¨λ μνλ₯Ό κ΄λ¦¬νλ κ²μ μ’μ λ³΄μΌ μ μλ€. νμ§λ§ λ©μλλ₯Ό μ€ννκΈ° μν΄ μκΈ΄ λ§μ λΆκΈ°λ₯Ό 보μλΌ. μνκ° κ³μν΄μ μ겨λ κ²½μ°, κΈ°λ₯μ μμ μ΄ λ°μνλ κ²½μ°, Enum κ°μ if νΉμ switch λ¬ΈμΌλ‘ νλ¨νλ κ²½μ°μλ OCP(κ°λ°©νμμμΉ)λ₯Ό μ€μνμ§ λͺ»νλ€. μνκ° λ§μμ§μλ‘ λ³΅μ‘ν΄μ§λ μ‘°κ±΄λ¬Έμ΄ μ¬λ¬ μ½λμμ μ€λ³΅ν΄μ μΆννκ³ κ·Έλ§νΌ μ½λ λ³κ²½μ μ΄λ ΅κ² λ§λ λ€.
μν ν¨ν΄μ λν΄ μ΄ν΄κ° λ°λ‘ λμ§λ μμ κ²μ΄λ€. νλ‘κ·Έλ¨μ ꡬμν λ μνκ° νμν κ³³μμ μν ν¨ν΄μ μ¬μ©νμ¬ νλ‘κ·Έλ¨μ μ€κ³ ν΄λ³΄λ€ 보면 μν ν¨ν΄μ λν μ΄ν΄κ° μμ°μ€λ½κ² λ κ²μ΄λ€. λμμΈ ν¨ν΄λΆν° νμ΅νλ λ°©μ보λ€λ κ²½νμ ν λλ‘ κ΅¬νμ ν΄λ³Έ ν λμμΈ ν¨ν΄κ³Ό λΉκ΅ν΄λ³΄λ©° νμ΅νλ λ°©μμ μΆμ²νλ€.
μ°Έκ³
- μ΄κ±°ν enum
- μνν¨ν΄ wikipedia
- κ°λ°μκ° λ°λμ μ 볡ν΄μΌν κ°μ²΄μ§ν₯κ³Ό λμμΈν¨ν΄