티스토리 뷰
스트래티지 (전략적 패턴)
- 객체의 행위를 정의하고 구현함으로써 해당객체의 특정 행위에 대한 구현을 행동객체에 위임하여
해당객체와는 독립적으로 동작/행위를 구현하는 패턴
- 알고리즘군을 정의하고 각각을 캡슐화하여 사용할 수 있도록 만듬
- 알고리즘군: 어떤 일을 해야하는지를 정의해놓은(연관성 있는 기능들을 모아놓은 그룹)
- 각각의 알고리즘을 캡슐화시킴 (=클래스로 만들어서 관리함)
- 그 알고리즘들은 그룹들 내에서 서로 바꿀 수 있게 함
- 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있음
- 상속을 사용한다면?
- 슈퍼클래스에서 제공하는 기능과 다른 기능을 구현하고 싶을 땐, 하위 클래스에서 메소드를 재정의한다
-> 이런 하위클래스가 여러개일 경우, 같은 코드를 계속 재정의함으로써 코드가 중복됨
- 인터페이스를 사용한다면?
- 행위를 조금 바꾸기위해 인터페이스로 구현한 모든 서브클래스들을 다 고쳐야함
-> 인터페이스에는 코드가 없기에 코드 재사용이 불가
- 행동 기반으로 인터페이스를 나눈다
- FlyBehavior 인터페이스 집합: FlyWithWings , FlyNoWay 클래스
- 슈퍼클래스에서 직접 수행하는 것이 아니라, 각 행동클래스에게 위임한다
팩토리 패턴
1. 팩토리 메소드 패턴
- 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정함
- 클래스의 인스턴스를 만드는 일을 서브클래스에게 맡김
- 즉, new 키워드를 사용하는 부분은 서브클래스에 위임함으로써 객체 생성을 캡슐화하고 구상 클래스에 대한 의존성이 줄어듬
Duck duck;
if ( type == picnic ) duck = new MallardDuck();
else if ( type == hunting ) duck = new DecoyDuck();
else if ( type == inBathTub) duck = new RubberDuck();
// 뭔가 변경하거나 확장해야 할 때 코드를 다시 확인하고 추가 or 제거해야한다는 것을 의미함
- 바뀔 수 있는 부분을 찾아내서 바뀌지 않는 부분하고 분리시켜야 한다는 원칙
Pizza orderPizza(String type) {
Pizza pizza;
if(type.equals("cheese")) pizza = new CheesePizza();
else if(type.equals("greek")) pizza = new GreekPizza();
else if(type.equals("pepperoni")) pizza = new PepperoniPizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
public class SimplePizzaFactory {
public Pizza createPizza(String type){ //이런 경우에는 static메소드로 선언하는 경우가 종종 있음.
Pizza pizza = null;
if(pizza.equals("cheese")) pizza = new CheesePizza();
if(pizza.equals("pepper")) pizza = new PepperoniPizza();
if(pizza.equals("clam")) pizza = new ClamPizza();
if(pizza.equals("veggie")) pizza = new VeggiePizza();
return pizza;
}
}
public class PizzaStore{
SimplePizzaFactory simplePizzaFactory;
public PizzaStore(SimplePizzaFactory simplePizzaFactory) {
this.simplePizzaFactory = simplePizzaFactory;
}
public Pizza orderPizza(String type){
Pizza pizza;
pizza = simplePizzaFactory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
옵저버 패턴
- 나오게 된 배경
- 한 객체의 상태가 바뀔 경우 다른 객체들에게 변경됐다고 알려주는 경우
→ 상태를 가지고 있는 주체 객체와 상태의 변경을 알아야 하는 관찰 객체(Observer Object) 존재
→ 이들 관계는 1:1 또는 1:N이 될 수 있음
→ 서로 주고 받는 정보 단위가 클수록, 객체들의 규모가 클수록 객체들의 관계 복잡해짐, 구현 어려움
- 예시
- 뉴스머신 & 구독자 (Observer)
- Publisher 인터페이스 : Observer들을 관리하는 Method가짐, 구독을 원하는 옵저버를 받아 등록(add),
명단에서 옵저버를 제외 (delete), 등록된 옵저버들에게 정보를 알려줌 (notify Observer) - Observer 인터페이스 : 정보를 업데이트 해주는 Update method
- 정리
- 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들에게 연락이 가고 자동으로 정보가 갱신되는 1:N의 관계를 정의함
- 구현 방식은 크게 PULL (퍼블리셔->옵저버) , PUSH(옵저버->퍼블리셔)가 있음
- JAVA에서 기본으로 Observable 클래스와 Observer 인터페이스를 제공함
- Swing, Android 등에서 UI관련된 곳에서 이 패턴이 많이 사용됨
싱글톤 패턴
- 어떤 클래스가 최초 한번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 패턴
- 생성자가 여러번 호출되어도 실제로 생성되는 객체는 하나고, 최초 생성 이후 호출된 생성자는 최초에 생성한 객체를 반환함
- 인스턴스가 오직 1개만 생성되어야하는 경우에 사용하는 패턴
- 객체가 여러개 생성되면 설정 값이 변경될 위험이 있는 경우
- 하나의 인스턴스를 메모리에 등록해서 여러 스레드가 동시에 해당 인스턴스를 공유하여 사용하게끔 할 수 있으므로, 요청이 많은 곳에서 사용하면 효율을 높일 수 있음
- 주의할 점: 동시성(Concurrency)문제를 고려해서 설계해야함
- private 생성자와 static getInstance 메소드를 사용
- 쓰는 이유
- 메모리 낭비 방지
- 싱글톤으로 만들어진 클래스의 인스턴스는 전역 인스턴스 -> 다른 클래스의 인스턴스들이 데이터를 공유하기 쉬움
- 두번째 이용시부터는 객체 로딩 시간이 현저하게 줄어 성능이 좋아짐
- 문제점
- 싱글톤 인스턴스가 너무 많은 일을 하거나 많은 데이터를 공유시킬 경우 수정이 어려워짐
- 멀티쓰레드 환경에서 동기화 처리 안하면 인스턴스가 두개 생성될 수 있음
-> synchronized getInstance()
참고 :
friday.fun25.co.kr/blog/?p=280
medium.com/webeveloper/%EC%8B%B1%EA%B8%80%ED%84%B4-%ED%8C%A8%ED%84%B4-singleton-pattern-db75ed29c36
'개발참고 > ETC' 카테고리의 다른 글
[Git] 원격 브랜치 가져오기 (0) | 2023.02.04 |
---|
- Total
- Today
- Yesterday