行为模式共有11种:
观察者模式
模板方法模式
策略模式
职责链模式
状态模式
命令模式
中介者模式
迭代器模式
访问者模式
备忘录模式
解释器模式
以上 11 种行为型模式,除了模板方法模式和解释器模式是类行为型模式,其他的全部属于对象行为型模式。
1 观察者模式介绍
2 观察者模式原理
3 观察者模式实现
/*** 抽象观察者**/
public interface Observer {//update方法: 为不同的观察者更新行为定义一个相同的接口,不同的观察者对该接口有不同的实现public void update();
}
/*** 具体的观察者**/
public class ConcreteObserver1 implements Observer {@Overridepublic void update() {System.out.println("ConcreteObserver1 得到通知,更新状态! !");}
}
public class ConcreteObserver2 implements Observer{@Overridepublic void update() {System.out.println("ConcreteObserver2 得到通知,更新状态! !");}
}
/*** 抽象目标类**/
public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers();
}
import java.util.ArrayList;/*** 具体目标类**/
public class ConcreteSubject implements Subject {//定义集合,存储所有的观察者对象private ArrayList<Observer> observers = new ArrayList<>();//注册方法,向观察者集合增加一个观察者@Overridepublic void attach(Observer observer) {observers.add(observer);}//注销方法,用于从观察者集合中移除一个观察者@Overridepublic void detach(Observer observer) {observers.remove(observer);}//通知方法@Overridepublic void notifyObservers() {//遍历集合,调用每一个观察者的响应方法for (Observer observer : observers) {observer.update();}}
}
public class Client {public static void main(String[] args) {//创建目标类Subject subject = new ConcreteSubject();//注册观察者,注册多个subject.attach(new ConcreteObserver1());subject.attach(new ConcreteObserver2());//具体的主题内部发生改变,给所有注册的观察者发送通知subject.notifyObservers();}
}
4 观察者模式应用实例
来实现一个买房摇号的程序.摇号结束,需要通过短信告知用户摇号结果,还需要向MQ中保存用户本次摇号的信息.
1 ) 未使用设计模式
/*** 模拟买房摇号服务**/
public class DrawHouseService {//摇号抽签public String lots(String uId){if(uId.hashCode() % 2 == 0){return "恭喜ID为: " + uId + " 的用户,在本次摇号中中签!" ;}else{return "很遗憾,ID为: " + uId + "的用户,您本次未中签!" ;}}
}
/*** 开奖结果封装类**/
public class LotteryResult {private String uId; //用户idprivate String msg; //摇号信息private Date dateTime; //业务时间public LotteryResult(String uId, String msg, Date dateTime) {this.uId = uId;this.msg = msg;this.dateTime = dateTime;}@Overridepublic String toString() {return "LotteryResult{" +"uId='" + uId + '\'' +", msg='" + msg + '\'' +", dateTime=" + dateTime +'}';}public String getuId() {return uId;}public void setuId(String uId) {this.uId = uId;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Date getDateTime() {return dateTime;}public void setDateTime(Date dateTime) {this.dateTime = dateTime;}
}
/*** 开奖服务接口**/
public interface LotteryService {//开奖之后的业务操作public LotteryResult lottery(String uId);}
public class LotteryServiceImpl implements LotteryService {//注入摇号服务private DrawHouseService houseService = new DrawHouseService();@Overridepublic LotteryResult lottery(String uId) {//1.摇号String result = houseService.lots(uId);//2.发短信System.out.println("发送短信通知用户,ID为: " + uId +",您的摇号结果如下: " + result);//3.发送MQ信息System.out.println("记录用户摇号结果到MQ,ID为: " + uId +",摇号结果: " + result);return new LotteryResult(uId,result,new Date());}
}
使用观察者模式进行优化
/*** 事件监听接口**/
public interface EventListener {//充当观察者的角色,对结果进行监听void doEvent(LotteryResult result);
}
/*** 短信发送事件监听类**/
public class MessageEventListener implements EventListener {@Overridepublic void doEvent(LotteryResult result) {System.out.println("发送短信通知,用户ID: " + result.getuId()+",您的摇号结果为: " + result.getMsg());}
}
/*** MQ消息发送事件监听**/
public class MQEventListener implements EventListener{@Overridepublic void doEvent(LotteryResult result) {System.out.println("记录用户的摇号结果(MQ),用户ID: " + result.getuId()+ ",摇号结果: " + result.getMsg());}
}
/*** 事件处理类**/
public class EventManager {public enum EventType{MQ,Message}//监听器集合Map<Enum<EventType>, List<EventListener>> listeners = new HashMap<>();public EventManager(Enum<EventType>... operations) {for (Enum<EventType> operation : operations) {this.listeners.put(operation,new ArrayList<>());}}/*** 订阅* @param eventType 事件类型* @param listener 监听对象*/public void subscribe(Enum<EventType> eventType,EventListener listener){List<EventListener> users = listeners.get(eventType);users.add(listener);}/*** 取消订阅* @param eventType 事件类型* @param listener 监听对象*/public void unsubscribe(Enum<EventType> eventType,EventListener listener){List<EventListener> users = listeners.get(eventType);users.remove(listener);}/*** 通知* @param eventType* @param result*/public void notify(Enum<EventType> eventType, LotteryResult result){List<EventListener> users = listeners.get(eventType);for (EventListener listener : users) {listener.doEvent(result);}}
}
/*** 开奖服务接口**/
public abstract class LotteryService {private EventManager eventManager;public LotteryService() {//设置事件的类型eventManager = new EventManager(EventManager.EventType.MQ,EventManager.EventType.Message);//订阅eventManager.subscribe(EventManager.EventType.Message,new MessageEventListener());eventManager.subscribe(EventManager.EventType.MQ,new MQEventListener());}public LotteryResult lotteryAndMsg(String uId){LotteryResult lottery = lottery(uId);//发送通知eventManager.notify(EventManager.EventType.Message,lottery);eventManager.notify(EventManager.EventType.MQ,lottery);return lottery;}public abstract LotteryResult lottery(String uId);
}
public class LotteryServiceImpl extends LotteryService {//注入摇号服务private DrawHouseService houseService = new DrawHouseService();@Overridepublic LotteryResult lottery(String uId) {//1.摇号String result = houseService.lots(uId);return new LotteryResult(uId,result,new Date());}
}
测试
@Test
public void test2(){LotteryService ls = new LotteryServiceImpl();LotteryResult result = ls.lotteryAndMsg("1234567887654322");System.out.println(result);
}
5 观察者模式总结