GoF之观察者模式、状态模式详解

观察者(Observer Pattern)模式
一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。此种模式通常被用来实现事件处理系统。
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

优使用场景:
1、当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
2、当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象需要被改变。
3、当一个对象必须通知其他对象,而它又不能假定其他对象是谁。换言之,不希望这些对象是紧密耦合的。

具体实现:创建观察者和被观察者。观察者订阅被观察者的状态,当被观察者状态改变的时候会通知所有订阅的观察者的过程。
//观察者接口:
public abstract class Observer {
public abstract void update(String msg);
}
//第一个观察者:
public class F_Observer extends Observer {
public void update(String msg) {
System.out.println(F_Observer.class.getName() + " :" + msg);
}
}
//第二个观察者:
public class S_Observer extends Observer {
public void update(String msg) {
System.out.println(S_Observer.class.getName() + " :" + msg);
}
}
//第三个观察者:
public class T_Observer extends Observer {
public void update(String msg) {
System.out.println(T_Observer.class.getName() + " :" + msg);
}
}

//被观察者:
public class Subject {
private Listobservers =new ArrayList<>();
//状态改变
public void setMsg(String msg) {
notifyAll(msg);
}
//添加订阅
public void addAttach(Observerobserver) {
observers.add(observer);
}
//通知所有订阅的观察者
private void notifyAll(String msg) {
for (Observerobserver : observers) {
observer.update(msg);
}
}
}

//具体使用方法:
public class Client {
public static void main(String[] args) {
F_Observer fObserver = new F_Observer();
S_Observer sObserver = new S_Observer();
T_Observer tObserver = new T_Observer();
Subject subject = new Subject();
subject.addAttach(fObserver);
subject.addAttach(sObserver);
subject.addAttach(tObserver);
subject.setMsg(“msg change”);
}
}

状态(State Pattern)模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
优点:
1、封装了转换规则。
2、枚举可能的状态,在枚举状态之前需要确定状态种类。
3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
1、状态过多导致类膨胀。
2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

使用场景:
1、行为随状态改变而改变的场景。
2、条件、分支语句的代替者。

具体实现:创建一个 State 接口和实现了 State 接口的实体状态类。Context 是一个带有某个状态的类。
//创建一个接口
public interface State {
public void doAction(Context context);
}

//创建Context容器类。
public class Context {
private State state;

public Context(){
state =null;
}

public void setState(State state){
   this.state = state;

}

public State getState(){
   return state;

}
}

//创建实现接口的实体类A
public class StateA implements State {
public void doAction(Context context) {
System.out.println(“Player isin stateA”);
//改变状态
context.setState(this);
}

public String toString(){
   return "A State";

}
}
//创建实现接口的实体类B
public class SStateB implements State {

public void doAction(Context context) {
   System.out.println("Player isin stateB");
   context.setState(this);

}

public String toString(){
   return "B State";

}
}

//使用Context来查看当状态State改变时的行为变化。
public class Client {
public static void main(String[] args) {
Context context = new Context();

   StateA stateA = new StateA();
   stateA.doAction(context);
   System.out.println(context.getState().toString());

   Stateb stateB = new StateB();
   stateB.doAction(context);
   System.out.println(context.getState().toString());

}
}

更多技术分享,微信关注“专注一行代码”

https://mp.weixin.qq.com/s/Cmv6qlXIrZEK5aZ_bx808g

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值