🌷Dev

[Java] μ „λž΅ νŒ¨ν„΄ vs ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄ vs μƒνƒœ νŒ¨ν„΄

alreadykite 2024. 1. 9. 15:19
ν”„λ‘œμ νŠΈμ—μ„œ λŸ°νƒ€μž„ μ‹œ 객체λ₯Ό λ™μ μœΌλ‘œ κ΄€λ¦¬ν•˜κ³ , OCPλ₯Ό λ§Œμ‘±ν•˜λŠ” μ½”λ“œλ‘œ κ°œμ„ ν•˜κΈ° μœ„ν•΄ λ””μžμΈ νŒ¨ν„΄μ„ κ³ λ €ν•œ 과정을 κΈ°λ‘ν•˜μ˜€λ‹€.

 

 

1. μ „λž΅ νŒ¨ν„΄ vs ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄


ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ€ 좔상 클래슀λ₯Ό μƒμ†ν•˜λŠ” ꡬ쑰둜 μ„€κ³„λ˜μ–΄ μžˆλ‹€.

상속은 μƒμœ„ ν΄λž˜μŠ€μ™€ ν•˜μœ„ ν΄λž˜μŠ€κ°€ κ°•λ ₯ν•˜κ²Œ λ°€μ ‘λ˜μ–΄ μžˆμ–΄ 결합도가 λ†’λ‹€. λ˜ν•œ 상속 κ΄€κ³„λŠ” 컴파일 λ‹¨κ³„μ—μ„œ κ²°μ •λ˜κΈ° λ•Œλ¬Έμ— μ‹€ν–‰ 쀑 객체λ₯Ό 동적을 λ³€κ²½ν•˜λŠ” 것이 λΆˆκ°€ν•˜λ‹€. 

λŸ°νƒ€μž„ μ‹œ 객체λ₯Ό λ™μ μœΌλ‘œ 관리해야 ν•˜λŠ” κ²½μš°μ—λŠ” μ΄λŸ¬ν•œ 이유둜 ν…œν”Œλ¦Ώ λ©”μ„œλ“œ νŒ¨ν„΄μ€ μ ν•©ν•˜μ§€ μ•Šλ‹€.

 

 

 

 

2. μ „λž΅ νŒ¨ν„΄ vs μƒνƒœ νŒ¨ν„΄


2-1. μ „λž΅ νŒ¨ν„΄

μ „λž΅ νŒ¨ν„΄μ€ νŠΉμ • μž‘μ—…μ„ μˆ˜ν–‰ν•˜λŠ” 방법을 μΊ‘μŠν™”ν•˜κ³ , 이 방법듀을 μƒν˜Έ ꡐ체가 κ°€λŠ₯ν•˜λ„λ‘ ν•œ νŒ¨ν„΄μ΄λ‹€.

 

Context : λ³€κ²½λ˜μ§€ μ•ŠλŠ” 것, μ „λž΅ νŒ¨ν„΄μ„ μ΄μš©ν•˜λŠ” 역할을 ν•˜κ³  DIλ₯Ό 톡해 λ™μ μœΌλ‘œ μ „λž΅μ„ λ³€κ²½ν•œλ‹€.

Strategy : μ™ΈλΆ€μ—μ„œ λ™μΌν•œ λ°©μ‹μœΌλ‘œ μ•Œκ³ λ¦¬μ¦˜μ„ ν˜ΈμΆœν•˜λŠ” 방법을 λͺ…μ‹œν•΄μ€€λ‹€.

ConcreateStrategy : λ³€κ²½λ˜λŠ” 것, Strategyμ—μ„œ λͺ…μ‹œν•œ μ•Œκ³ λ¦¬μ¦˜μ„ κ΅¬ν˜„ν•œ 클래슀

 

μ˜ˆμ‹œ μ½”λ“œ

κ°„λ‹¨ν•œ 결제 방식 선택을 μœ„ν•œ μ „λž΅ νŒ¨ν„΄μ„ μ μš©ν•œ μ½”λ“œμ΄λ‹€.

결제 방식은 μΉ΄λ“œ, ν˜„κΈˆ 두 κ°€μ§€ 방식이 μžˆλ‹€.

// μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ 

interface PaymentStrategy {
    void pay(int amount);
}
// 콘크리트 μ „λž΅ 클래슀

class CreditCardStrategy implements PaymentStrategy {
    private String cardNumber;

    public CreditCardStrategy(String cardNumber) {
        this.cardNumber = cardNumber;
    }

    @Override
    public void pay(int amount) {
        System.out.println("Paying " + amount + " using Credit Card.");
    }
}

class PaypalStrategy implements PaymentStrategy {
    private String emailId;

    public PaypalStrategy(String emailId) {
        this.emailId = emailId;
    }

    @Override
    public void pay(int amount) {
        System.out.println("Paying " + amount + " using Paypal.");
    }
}
// μ»¨ν…μŠ€νŠΈ 클래슀

class ShoppingCart {
    private PaymentStrategy paymentStrategy;

    public ShoppingCart(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy; // μ „λž΅μ˜ μƒμ„±μž μ£Όμž…
    }

    public void checkout(int amount) {
        paymentStrategy.pay(amount);
    }
}
public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart(new CreditCardStrategy("1234-5678-9012-3456"));
        cart.checkout(100);

        cart = new ShoppingCart(new PaypalStrategy("myemail@example.com"));
        cart.checkout(200);
    }
}

 

2-2. μƒνƒœ νŒ¨ν„΄

μƒνƒœ νŒ¨ν„΄μ€ 객체의 λ‚΄λΆ€ μƒνƒœμ— 따라 ν–‰μœ„λ₯Ό λ³€κ²½ν•΄μ£ΌλŠ” λ””μžμΈ νŒ¨ν„΄μ΄λ‹€.

 

Context : ν˜„μž¬ μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” μƒνƒœ 객체λ₯Ό κ°€μ§€λ©°, μƒνƒœμ— 따라 λ‹€λ₯Έ 행동을 μˆ˜ν–‰ν•œλ‹€. νŠΉμ • μƒνƒœμ— λŒ€ν•œ 행동을 직접 κ΅¬ν˜„ν•˜μ§€ μ•Šκ³ , ν˜„μž¬ μƒνƒœ 객체에 μœ„μž„ν•œλ‹€.

State : λͺ¨λ“  ꡬ체적인 μƒνƒœ ν΄λž˜μŠ€λ“€μ΄ κ΅¬ν˜„ν•΄μ•Ό ν•˜λŠ” λ©”μ†Œλ“œλ“€μ„ μ •μ˜ν•œλ‹€. 이 λ©”μ†Œλ“œλ“€μ€ μƒνƒœμ— 따라 λ‹¬λΌμ§€λŠ” 행동을 μ •μ˜ν•œλ‹€.

ConcreateState: μƒνƒœ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀, 각 ν΄λž˜μŠ€λŠ” 객체가 νŠΉμ • μƒνƒœμ— μžˆμ„ λ•Œ μ–΄λ–»κ²Œ 행동해야 ν•˜λŠ”μ§€λ₯Ό μ •μ˜ν•œλ‹€. 예λ₯Ό λ“€μ–΄, "μ—΄λ¦Ό", "λ‹«νž˜", "μΌμ‹œμ •μ§€"λ“±μ˜ μƒνƒœκ°€ μžˆμ„ 수 있으며 각각의 μƒνƒœμ— λŒ€ν•œ 행동 둜직이 이 ν΄λž˜μŠ€μ— κ΅¬ν˜„λœλ‹€. 

μƒνƒœ κ°μ²΄λž€
ν˜„μž¬ 객체의 μƒνƒœλ₯Ό λ‚˜νƒ€λ‚΄λŠ” 객체λ₯Ό λ§ν•œλ‹€. μƒνƒœ νŒ¨ν„΄μ—μ„œλŠ” 이 μƒνƒœ 객체가 μ‹œμŠ€ν…œμ˜ 행동을 κ²°μ •ν•œλ‹€.
Context κ°μ²΄λŠ” μƒνƒœ 객체λ₯Ό μ‚¬μš©ν•˜μ—¬ ν˜„μž¬ μƒνƒœμ— λ§žλŠ” 행동을 μˆ˜ν–‰ν•˜κ²Œ λœλ‹€. 
즉, μƒνƒœ κ°μ²΄λŠ” Concreate 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ§ν•œλ‹€. κ·Έλž˜μ„œ μƒνƒœ κ°μ²΄λ§ˆλ‹€ λ‹€λ₯΄κ²Œ κ΅¬ν˜„λ˜μ–΄ μžˆλŠ” 행동이 ν˜„μž¬ μƒνƒœ 객체에 λ”°λΌμ„œ ν˜ΈμΆœλ˜λŠ” 것이닀. 
(μ•„λž˜μ˜ μ˜ˆμ‹œ μ½”λ“œμ—μ„œ ν˜„μž¬ μ‹ ν˜Έλ“± λΆˆλΉ›(μƒνƒœ 객체)이 λΉ¨κ°„λΆˆμΌ λ•Œ changeSignal()을 ν˜ΈμΆœν•˜λ©΄ μ‹ ν˜Έλ“±μ΄ 초둝뢈이 되고, ν˜„μž¬ μƒνƒœ 객체가 λ…Έλž€λΆˆμΌλ•Œ changeSignal()을 ν˜ΈμΆœν•˜λ©΄ μ‹ ν˜Έλ“±μ΄ λΉ¨κ°„λΆˆμ΄ λ˜λŠ”κ²ƒμ²˜λŸΌ)

 

μ˜ˆμ‹œ μ½”λ“œ

κ°„λ‹¨ν•œ ꡐ톡 μ‹ ν˜Έλ“± μ‹œμŠ€ν…œμ˜ μ˜ˆμ‹œ μ½”λ“œμ΄λ‹€.

μ‹ ν˜Έλ“± λΆˆλΉ›μ€ λΉ¨κ°„μƒ‰μΌλ•ŒλŠ” λ…Ήμƒ‰μœΌλ‘œ, λ…Ήμƒ‰μΌλ•ŒλŠ” λ…Έλž€μƒ‰μœΌλ‘œ, λ…Έλž€μƒ‰μΌ λ•ŒλŠ” λΉ¨κ°„μƒ‰μœΌλ‘œ λ³€κ²½λ˜μ–΄μ•Ό ν•œλ‹€.

μ—¬κΈ°μ„œ μƒνƒœ κ°μ²΄λŠ” μ‹ ν˜Έλ“±μ˜ ν˜„μž¬ 색깔을 λ‚˜νƒ€λ‚΄λ©°, μ»¨ν…μŠ€νŠΈ κ°μ²΄λŠ” 이 μƒνƒœμ— 따라 μ‹ ν˜Έλ“±μ˜ 행동을 κ²°μ •ν•œλ‹€.

// μƒνƒœ μΈν„°νŽ˜μ΄μŠ€

public interface State {
    void changeState(TrafficLight trafficLight);
}
// 콘크리트 μƒνƒœ 클래슀

public class RedLightState implements State {

    @Override
    public void changeState(TrafficLight trafficLight) {
        System.out.println("λΉ¨κ°„ λΆˆμ—μ„œ 초둝 뢈둜 λ°”λ€λ‹ˆλ‹€.");
        trafficLight.setState(new GreenLightState());
    }
}

public class GreenLightState implements State{
    @Override
    public void changeState(TrafficLight trafficLight) {
        System.out.println("초둝 λΆˆμ—μ„œ λΉ¨κ°„ 뢈둜 λ°”λ€λ‹ˆλ‹€.");
        trafficLight.setState(new RedLightState());
    }
}

public class YellowLightState implements State{
    @Override
    public void changeState(TrafficLight trafficLight) {
        System.out.println("λ…Έλž€ λΆˆμ—μ„œ λΉ¨κ°„ 뢈둜 λ°”λ€λ‹ˆλ‹€.");
        trafficLight.setState(new RedLightState());
    }
}
// μ»¨ν…μŠ€νŠΈ 클래슀

public class TrafficLight {
    private State state;

    public TrafficLight() {
        this.state = new RedLightState();
    }

    public void changeSignal() {
        state.changeState(this);
    }

    public void setState(State state) {
        this.state = state;
    }
}
public class Main {
    public static void main(String[] args) {
        TrafficLight trafficLight = new TrafficLight();

        for (int i = 0; i < 6; i++) {
            trafficLight.changeSignal();
        }
    }
}

 

μ‹€ν–‰ κ²°κ³Ό

 

 

2-3. 정리

곡톡점

β‘  μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ Concreate classλ₯Ό μΊ‘μŠν™” ν•œλ‹€.

β‘‘ Context classλŠ” 영ν–₯을 λ°›μ§€ μ•Šκ³ , 변경에 μœ μ—°ν•œ λŒ€μ²˜κ°€ κ°€λŠ₯ν•˜λ‹€. → OCPλ₯Ό λ§Œμ‘±ν•œλ‹€. 

 

 

차이점

β‘  ν΄λΌμ΄μ–ΈνŠΈκ°€ DIλ₯Ό 톡해 μƒνƒœλ₯Ό μ£Όμž…(μ„€μ •)ν•΄μ£ΌλŠ” μ „λž΅ νŒ¨ν„΄κ³ΌλŠ” 달리, μƒνƒœ νŒ¨ν„΄μ€ μ£Όμž… λ°›λŠ” 것이 μ—†κ³  λ‘œμ§μ„ λŒλ©΄μ„œ ν˜„μž¬ 객체 μƒνƒœμ— 따라 ν–‰μœ„λ₯Ό λ³€κ²½ν•œλ‹€. 

 

[μ „λž΅ νŒ¨ν„΄]

public class Main {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart(new CreditCardStrategy("1234-5678-9012-3456"));
        cart.checkout(100);

        cart = new ShoppingCart(new PaypalStrategy("myemail@example.com"));
        cart.checkout(200);
    }
}

μ „λž΅ νŒ¨ν„΄μ˜ 경우 main λ©”μ„œλ“œμ—μ„œ μ»¨ν…μŠ€νŠΈ 클래슀 객체λ₯Ό μƒμ„±ν•˜κ³  μƒμ„±μž μ£Όμž…μ„ 톡해 μ „λž΅μ„ λ³€κ²½ν•œλ‹€.

 

class ShoppingCart {
    private PaymentStrategy paymentStrategy;

    public ShoppingCart(PaymentStrategy paymentStrategy) { // μƒμ„±μž μ£Όμž…
        this.paymentStrategy = paymentStrategy;
    }

    public void checkout(int amount) {
        paymentStrategy.pay(amount);
    }
}

μ»¨ν…μŠ€νŠΈ ν΄λž˜μŠ€λŠ” μ „λž΅ μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μ˜ μ „λž΅ 객체λ₯Ό μ£Όμž… λ°›λŠ”λ‹€.

 

[μƒνƒœ νŒ¨ν„΄]

public class Main {
    public static void main(String[] args) {
        TrafficLight trafficLight = new TrafficLight();

        for (int i = 0; i < 6; i++) {
            trafficLight.changeSignal();
        }
    }
}

μƒνƒœ νŒ¨ν„΄μ˜ 경우 main ν΄λž˜μŠ€μ—μ„œ 객체λ₯Ό μ„ μ–Έν•˜κ³  λ©”μ„œλ“œ 호좜만 ν•œλ‹€. 

 

public class TrafficLight {
    private State state; // μƒνƒœ μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μ˜ λ³€μˆ˜ μ„ μ–Έ

    public TrafficLight() {
        this.state = new RedLightState();
    }

    public void changeSignal() {
        state.changeState(this); 
    }

    // setter둜 μƒνƒœ 객체 λ³€κ²½
    public void setState(State state) {
        this.state = state;
    }
}

μ»¨ν…μŠ€νŠΈ ν΄λž˜μŠ€μ—μ„œ λ‘œμ§μ— 따라 μƒνƒœ μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μ˜ μƒνƒœ 객체듀을 λ³€κ²½ν•œλ‹€.

 

public class YellowLightState implements State{
    @Override
    public void changeState(TrafficLight trafficLight) {
        System.out.println("λ…Έλž€ λΆˆμ—μ„œ λΉ¨κ°„ 뢈둜 λ°”λ€λ‹ˆλ‹€.");
        trafficLight.setState(new RedLightState());
    }
}

main λ©”μ†Œλ“œμ—μ„œ ν˜ΈμΆœν•œ changeSignal() λ©”μ†Œλ“œ λ‚΄λΆ€λ₯Ό 보면 setState() λ©”μ†Œλ“œλ₯Ό 톡해 객체 μƒνƒœμ— 따라 λ‹€λ₯Έ 행동이 ν˜ΈμΆœλœλ‹€.

 

β‘‘  μ „λž΅ νŒ¨ν„΄μ€ 객체듀이 ν•  수 μžˆλŠ” ν–‰μœ„μ— λŒ€ν•΄ Concreate 클래슀λ₯Ό λ§Œλ“€κ³  μœ μ‚¬ν•œ ν–‰μœ„λ“€μ„ μΊ‘μŠν™”ν•˜κ³ , μƒνƒœ νŒ¨ν„΄μ€ μƒνƒœμ— λ”°λ₯Έ 행동을 μΊ‘μŠν™”ν•œλ‹€. 

 

 

 

 

βœ”οΈ DIλ₯Ό ν†΅ν•œ μ „λž΅μ— λ”°λ₯Έ 객체λ₯Ό λ™μ μœΌλ‘œ λ³€κ²½ν•˜λŠ” μž‘μ—…μ΄ ν•„μš”ν–ˆλ˜ ν”„λ‘œμ νŠΈμ—μ„œλŠ” μ „λž΅ νŒ¨ν„΄μ„ μ μš©ν•˜μ˜€λ‹€.