전략패턴

HS K·2023년 2월 15일

전략패턴

객체의 행위를 바꾸고 싶은 경우 '직접' 수정하지 않고 전략이라고 부르는 '캡슐화한 알고리즘'을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴

실제 라이브러리로는 인증모듈에 쓰이는 passport가 있다.

  • 소셜로그인때 쓰인다.

※ 컨텍스트 : 프로그래밍에서 상황, 맥락, 문맥을 의미하고 개발자가 어떤 작업을 완료하는데 필요한 관련된 모든 정보를 말한다.

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
interface PaymentStrategy {
    public void pay(int amount);
}

class KAKAOCardStrategy implements PaymentStrategy {
    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;
    
    public KAKAOCardStrategy(String nm, String ccNum, String cvv, String expiryDate) {
        this.name = nm;
        this.cardNumber = ccNum;
        this.cvv = cvv;
        this.dateOfExpiry = expiryDate;
    }
    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid using KAKAOCard.");
    }
}
class LUNACardStrategy implements PaymentStrategy {
    private String emailId;
    private String password;
    public LUNACardStrategy(String email, String pwd) {
        this.emailId = email;
        this.password = pwd;
    }
    @Override
    public void pay(int amount) {
        System.out.println(amount + " paid using LUNACard.");
    }
}
class Item {
    private String name;
    private int price;
    public Item(String name, int cost) {
        this.name = name;
        this.price = cost;
    }
    public String getName() {
        return name;
    }
    public int getPrice() {
        return price;
    }
}
class ShoppingCart {
    List < Item > items;
    public ShoppingCart() {
        this.items = new ArrayList < Item > ();
    }
    public void addItem(Item item) {
        this.items.add(item);
    }
    public void removeItem(Item item) {
        this.items.remove(item);
    }
    public int calculateTotal() {
        int sum = 0;
        for (Item item: items) {
            sum += item.getPrice();
        }
        return sum;
    }
    public void pay(PaymentStrategy paymentMethod) {
        int amount = calculateTotal();
        paymentMethod.pay(amount);
    } //앞에서 만든 strategy가 담겨서 Override된 method로 구동이 되어서 지불되는 것을 알 수 있다. 
}
public class HelloWorld {
    public static void main(String[] args) {
            ShoppingCart cart = new ShoppingCart();
            Item A = new Item("kundolA", 100);
            Item B = new Item("kundolB", 300);
            cart.addItem(A);
            cart.addItem(B);
            // pay by LUNACard
            cart.pay(new LUNACardStrategy("kundol@example.com", "pukubababo"));
            // pay by KAKAOBank
            cart.pay(new KAKAOCardStrategy("Ju hongchul", "123456789", "123", "12/01"));
            } }
/*
400 paid using LUNACard.
400 paid using KAKAOCard.
*/
var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy( function(username, password, done) {
{
User.findOne({ username: username }, function (err, user)
if (err) { return done(err); } if (!user) {
return done(null, false, { message: 'Incorrect
username.' });
            }
if (!user.validPassword(password)) {
return done(null, false, { message: 'Incorrect
password.' });
            }
} ));
return done(null, user); });

cart.pay()

cart라는 형이 유지가 되지만

cart.pay(new LUNACardStrategy("kundol@gmail.com", "pukubabo"));

인자들만 strategy로 캡슐화하여 넣으면 로직을 짤때 쉬워진다.


부록 - 프로그래밍 컨텍스트

컨텍스트

  1. 어떤 종류의 상태, 환경을 캡슐화한 것을 말함.
  2. 작업이 중단 되고 나중에 같은 지점에서 계속 될 수 있도록 저장하는 최소 데이터 집합.(컨텍스트스위칭)

컨텍스트는 context와 contextual information으로 크게 나눠지는데 다음과 같습니다.
1. 병원에 가면 “이름”과 주민등록번호 앞자리를 말해야죠? 자 여기서 “병원에
방문”하는 context에서 여러분의 이름은 contextual information이 됩니다.
2. HTTP요청을 하는 context에서 HTTP Header는 contextual inforamation이라고 할
수 있음.
3. 트랜잭션이라는 context에서 트랜잭션 ID가 contextual information 이라고 할 수
있습니다.
이러한 이론을 기반으로 한 다양한 모듈 또는 API로는 react.js에서는 전역적으로 “상태”값을 넘길 수 있는 context API가 있습니다.

const ThemeContext = React.createContext('light');
class App extends React.Component {
    render() {
        return ( 
          <ThemeContext.Provider value = "dark" >
            <Toolbar / > < /ThemeContext.Provider>
        );
    }
}

function Toolbar() {
    return (
      <div > 
            < ThemedButton />
      </div> 
    );
}

class ThemedButton extends React.Component {
  static contextType = ThemeContext;
  render() {
     return <Button theme = {this.context} />; 
  }
}

React에서 context API를 통해 전역적으로 static contextType을 통해 상태관리를 하는 모습.

profile
주의사항 : 최대한 정확하게 작성하려고 하지만, 틀릴내용이 있을 수도 있으니 유의!

0개의 댓글