行为模式共有11种:
观察者模式
模板方法模式
策略模式
职责链模式
状态模式
命令模式
中介者模式
迭代器模式
访问者模式
备忘录模式
解释器模式
以上 11 种行为型模式,除了模板方法模式 和解释器模式是类行为型模式,其他的全部属于对象行为型模式。
1 观察者模式介绍
2 观察者模式原理
3 观察者模式实现
java
/**
* 抽象观察者
**/
public interface Observer {
//update方法: 为不同的观察者更新行为定义一个相同的接口,不同的观察者对该接口有不同的实现
public void update();
}
java
/**
* 具体的观察者
**/
public class ConcreteObserver1 implements Observer {
@Override
public void update() {
System.out.println("ConcreteObserver1 得到通知,更新状态! !");
}
}
java
public class ConcreteObserver2 implements Observer{
@Override
public void update() {
System.out.println("ConcreteObserver2 得到通知,更新状态! !");
}
}
java
/**
* 抽象目标类
**/
public interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
java
import java.util.ArrayList;
/**
* 具体目标类
**/
public class ConcreteSubject implements Subject {
//定义集合,存储所有的观察者对象
private ArrayList<Observer> observers = new ArrayList<>();
//注册方法,向观察者集合增加一个观察者
@Override
public void attach(Observer observer) {
observers.add(observer);
}
//注销方法,用于从观察者集合中移除一个观察者
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
//通知方法
@Override
public void notifyObservers() {
//遍历集合,调用每一个观察者的响应方法
for (Observer observer : observers) {
observer.update();
}
}
}
java
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 ) 未使用设计模式
java
/**
* 模拟买房摇号服务
**/
public class DrawHouseService {
//摇号抽签
public String lots(String uId){
if(uId.hashCode() % 2 == 0){
return "恭喜ID为: " + uId + " 的用户,在本次摇号中中签!" ;
}else{
return "很遗憾,ID为: " + uId + "的用户,您本次未中签!" ;
}
}
}
java
/**
* 开奖结果封装类
**/
public class LotteryResult {
private String uId; //用户id
private String msg; //摇号信息
private Date dateTime; //业务时间
public LotteryResult(String uId, String msg, Date dateTime) {
this.uId = uId;
this.msg = msg;
this.dateTime = dateTime;
}
@Override
public 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;
}
}
java
/**
* 开奖服务接口
**/
public interface LotteryService {
//开奖之后的业务操作
public LotteryResult lottery(String uId);
}
java
public class LotteryServiceImpl implements LotteryService {
//注入摇号服务
private DrawHouseService houseService = new DrawHouseService();
@Override
public 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());
}
}
使用观察者模式进行优化
java
/**
* 事件监听接口
**/
public interface EventListener {
//充当观察者的角色,对结果进行监听
void doEvent(LotteryResult result);
}
java
/**
* 短信发送事件监听类
**/
public class MessageEventListener implements EventListener {
@Override
public void doEvent(LotteryResult result) {
System.out.println("发送短信通知,用户ID: " + result.getuId()
+",您的摇号结果为: " + result.getMsg());
}
}
java
/**
* MQ消息发送事件监听
**/
public class MQEventListener implements EventListener{
@Override
public void doEvent(LotteryResult result) {
System.out.println("记录用户的摇号结果(MQ),用户ID: " + result.getuId()
+ ",摇号结果: " + result.getMsg());
}
}
java
/**
* 事件处理类
**/
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);
}
}
}
java
/**
* 开奖服务接口
**/
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);
}
java
public class LotteryServiceImpl extends LotteryService {
//注入摇号服务
private DrawHouseService houseService = new DrawHouseService();
@Override
public LotteryResult lottery(String uId) {
//1.摇号
String result = houseService.lots(uId);
return new LotteryResult(uId,result,new Date());
}
}
测试
java
@Test
public void test2(){
LotteryService ls = new LotteryServiceImpl();
LotteryResult result = ls.lotteryAndMsg("1234567887654322");
System.out.println(result);
}
5 观察者模式总结