⛳ 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들에게 notify()되며 자동으로 내용이 update()되는 방식. 다수에게 상태를 전달해주는(=상태를 가지고 있는)
Subject
와 내용을 갱신받는(=의존성을 가지고 있는)Observer(옵저버)
로 나눌 수 있다.
사용 상황 : 서로의 정보를 주고 받는 크기가 커지면서 객체의 관계성이 복잡해질 때, 의존성
을 기준으로 나누어 가이드라인을 제공하고자 할 때 사용한다.
예시 : 유튜브 채널과 구독자와의 관계와 비슷하다. 구독, 구독 취소, 영상 업로드 등..
특징 : subject
와 Observer
사이는 느슨한 결합성을 가진다.
상호작용은 하지만 서로 잘 모르는 사이!
Observer Interface를 구현하여 추가, 교체, 동적 변경이 가능(OCP원칙 보장)하다. 따라서 Observer가 변경된다고 해서 subject의 코드를 바꿀 필요가 없다.
장점
단점
public interface Publichser{
public void add(Observer observer);
public void delete(Observer observer);
public void notifyObserver();
}
public interface Observer{
public void update(String title, String news);
}
public class NewMachine implements Publisher{
private ArrayList<Observer> observers;
private String title;
private String news;
public NewMachine(){
observers = new ArrayList<>();
}
@Override
public void add(Observer observer){
observers.add(observer);
}
@Override
pubic void delete(Observer observer){
int idx = observers.indexOf(observer);
observers.remove(idx);
}
@Override public void notifyObserver(){
for(Observer observer:observers){
observer.update(title, news);
}
}
public void setNewsInfo(String title, String news){
this.title = title;
this.news = news;
notifyObserver();
}
public String getTitle(){
return title;
}
public String getNews(){
return news;
}
}
public class EventSubscriber implements Observer{
private String newsString;
private Publisher publisher;
public EventSubscriber(Publisher publisher){
this.publisher = publisher;
publisher.add(this);
}
@Override
public void update(String title, String news){
newsString = title + " " + news;
display();
}
public void withdraw(){
publisher.delete(this);
}
public void display(){
System.out.println("이벤트 유저");
System.out.println(newsString);
}
}
새로운 로직을 추가하거나 변경할 때 한 번에 효율적으로 변경하도록 하기 위해, 어떤 동작을 하는 로직을 하나로 묶어 캡슐화하는 방식
attack, move을 위한 인터페이스를 만들고 각각 실현한 클래스를 만들어야 한다. 즉, 구체적인 공격, 이동 방식이 MovingStrategy, AttackStrategy 인터페이스에 의해 캡슐화되어 있다.
외부에서 로봇 객체으 attack, move방식을 임의로 바꾸도록 변경해주는 setter메서드가 필요하다.
로봇 클래스
public abstract class Robot {
private String name;
private AttackStrategy attackStrategy;
private MovingStrategy movingStrategy;
public Robot(String name) { this.name = name; }
public String getName() { return name; }
public void attack() { attackStrategy.attack(); }
public void move() { movingStrategy.move(); }
// 집약 관계, 전체 객체가 메모리에서 사라진다 해도 부분 객체는 사라지지 않는다.
// setter 메서드
public void setAttackStrategy(AttackStrategy attackStrategy) {
this.attackStrategy = attackStrategy; }
public void setMovingStrategy(MovingStrategy movingStrategy) {
this.movingStrategy = movingStrategy; }
}
https://gmlwjd9405.github.io/2018/07/06/strategy-pattern.html
public class TaekwonV extends Robot {
public TaekwonV(String name) { super(name); }
}
public class Atom extends Robot {
public Atom(String name) { super(name); }
}
https://gmlwjd9405.github.io/2018/07/06/strategy-pattern.html
// Attack 인터페이스
interface AttackStrategy { public void attack(); }
// Attack 구체적인 클래스
public class MissileStrategy implements AttackStrategy {
public void attack() { System.out.println("I have Missile."); }
}
public class PunchStrategy implements AttackStrategy {
public void attack() { System.out.println("I have strong punch."); }
}
https://gmlwjd9405.github.io/2018/07/06/strategy-pattern.html
// Moving 인터페이스
interface MovingStrategy { public void move(); }
// Moving 구체적인 클래스
public class FlyingStrategy implements MovingStrategy {
public void move() { System.out.println("I can fly."); }
}
public class WalkingStrategy implements MovingStrategy {
public void move() { System.out.println("I can only walk."); }
}
https://gmlwjd9405.github.io/2018/07/06/strategy-pattern.html
public class Client {
public static void main(String[] args) {
Robot taekwonV = new TaekwonV("TaekwonV");
Robot atom = new Atom("Atom");
/* 수정된 부분: 전략 변경 방법 */
taekwonV.setMovingStrategy(new WalkingStrategy());
taekwonV.setAttackStrategy(new MissileStrategy());
atom.setMovingStrategy(new FlyingStrategy());
atom.setAttackStrategy(new PunchStrategy());
/* 아래부터는 동일 */
System.out.println("My name is " + taekwonV.getName());
taekwonV.move();
taekwonV.attack();
System.out.println()
System.out.println("My name is " + atom.getName());
atom.move();
atom.attack();
}
}
https://gmlwjd9405.github.io/2018/07/06/strategy-pattern.html