1.引子
不知不觉,这是我们面向对象编程内功心法系列的第十三篇文章了。这一篇我将给你分享观察者设计模式,它是行为型设计模式中的一种。
前面通过六篇文章,我分别给你分享了创建型设计模式中的单例、工厂、建造者设计模式,与结构型设计模式中的代理、装饰器、适配器设计模式。今天我们开始行为型设计模式的分享。
在这里,不知道你是否思考过这么一个问题,设计模式分类为创建型、结构型、行为型,都是基于什么考虑呢?
让我们一起来理一理吧。
我们说在实际项目中,应用设计模式最大的收益是实现解耦,从而获得项目更好的扩展性与灵活性。那么创建型、结构型、行为型是如何去分类的呢?
- 创建型,解决对象的创建问题,将对象的创建与使用解耦
- 结构型,解决了对象的组装问题,将对象的功能结构解耦
- 行为型,解决了对象的交互问题,将对象的行为解耦
你可以仔细琢磨一下设计模式不同分类的关注点。在创建型设计模式中,主要关注对象的创建,比如说单例、工厂、建造者设计模式;在结构型设计模式中,主要关注对象之间的组装,比如说代理、装饰器、适配器设计模式;在行为型设计模式中,主要关注对象之间的交互,比如说观察者、模板、策略、责任链设计模式。
那么接下来,让我们一起来看行为型设计模式中的观察者设计模式。观察者设计模式在实际项目中,应用非常普遍。小到代码层面,大到架构层面,甚至产品设计都能有它的用武之地。举几个例子
- 电商降价通知机制实现
- 用户注册送积分,发放优惠券功能需求实现
- 发布-订阅机制实现
- 生产者-消费者编程模型实现
- 等
本篇文章,我将通过模拟电商降价通知机制实现案例,给你分享如何完整的通过自定义的方式实现观察者模式,以及借助jdk提供的接口来实现观察者模式。让我们开始吧
2.案例
当今我们的购物习惯,早已从传统线下购物,转变到了线上购物。你是不是经常会到各大电商网站平台看一看喜欢的商品,关注它什么时候降价,并且留下手机号码点击降价通知。
今天我们就通过观察者模式来实现这个案例。观察者设计模式代码实现非常简单,容易理解,你主要需要关注的点有
- 有哪些角色?观察者、被观察者
- 观察者中,需要有处理更新通知的能力
- 被观察者中,需要有注册观察者、移除观察者、通知观察者的能力
关于这几个关注点,如果你暂时理解起来有一些困难,那不要紧,等案例实现以后,你再对照着代码一起来领会,相信你一定会有所收获。
2.1.自定义实现观察者模式
2.1.1.观察者接口
/**
* 自定义实现观察者模式案例:观察者接口
*
* @author ThinkPad
* @version 1.0
* @date 2021/3/21 8:02
*/
public interface Observer {
/**
* 处理更新通知
* @param o
* @param msg
*/
void handle(Observable o, Object msg);
}
2.1.2.被观察者接口
/**
* 自定义实现观察者模式案例:被观察者接口
*
* @author ThinkPad
* @version 1.0
* @date 2021/3/21 8:00
*/
public interface Observable {
/**
* 注册观察者
* @param observer
*/
void registerObserver(Observer observer);
/**
* 移除观察者
* @param observer
*/
void removeObserver(Observer observer);
/**
* 通知观察者
* @param msg
*/
void notifyObservers(Object msg);
}
2.1.3.观察者具体实现
/**
* 观察者设计模式案例:观察者实现
*业务场景描述:电商降价通知
* @author ThinkPad
* @version 1.0
* @date 2021/3/21 8:12
*/
public class ProductPriceObserverBySelf implements Observer{
/**
* 处理更新通知
* @param o
* @param msg
*/
@Override
public void handle(Observable o, Object msg) {
// 商品对象
ProductBySelf product = (ProductBySelf)o;
// 输出消息
System.out.println(msg);
// 输出商品信息
// 输出价格变化
System.out.println("ProductPriceObserver观察到商品【"
+ product.getName() + "】价格更新为【" + product.getPrice() + "】.");
}
}
2.1.4.被观察者具体实现
/**
* 自定义实现观察者模式案例:被观察者接口实现
*业务场景描述:电商降价通知
* @author ThinkPad
* @version 1.0
* @date 2021/3/21 8:07
*/
public class ProductBySelf implements Observable {
/**
* 观察者集合
*/
private Vector<Observer> vec = new Vector<>();
// 商品名称
private String name;
// 商品价格
private float price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
/**
* 重点关注:当设置价格,即价格发生变化后,发出价格变更通知
* @param price
*/
public void setPrice(float price) {
this.price = price;
// 发出价格更新通知
notifyObservers("价格发生了变化!");
}
/**
* 注册观察者
* @param observer
*/
@Override
public void registerObserver(Observer observer) {
vec.add(observer);
}
/**
* 移除观察者
* @param observer
*/
@Override
public void removeObserver(Observer observer) {
vec.remove(observer);
}
/**
* 通知观察者
* @param msg
*/
@Override
public void notifyObservers(Object msg) {
for(Observer observer : vec){
observer.handle(this, msg);
}
}
}
2.1.5.使用案例
public static void main(String[] args) {
// 创建观察者对象
Observer observer = new ProductPriceObserverBySelf();
// 创建被观察者对象(商品)
ProductBySelf product = new ProductBySelf();
product.setName("苹果手机");
// 注册观察者
product.registerObserver(observer);
// 更新商品价格
product.setPrice(99.0f);
}
#执行结果
价格发生了变化!
ProductPriceObserver观察到商品【苹果手机】价格更新为【99.0】.
Process finished with exit code 0
2.2.基于jdk提供的接口实现观察者模式
在定义观察者模式实现案例中,我们需要定义观察者,与被观察者接口。事实上jdk给我们提供了观察者接口java.util.Observer,被观察者接口java.util.Observable。让我们在实际项目中,更加容易实现观察者模式。
2.2.1.观察者具体实现
/**
* 观察者设计模式案例:基于jdk提供的观察者实现
*业务场景描述:电商降价通知
* @author ThinkPad
* @version 1.0
* @date 2021/3/21 7:49
*/
public class ProductPriceObserverByJdk implements Observer{
@Override
public void update(Observable o, Object arg) {
// 商品,与商品价格
ProductByJdk product = (ProductByJdk)o;
Float price = ((Float) arg).floatValue();
// 输出价格变化
System.out.println("ProductPriceObserver观察到商品【"
+ product.getName() + "】价格更新为【" + price + "】.");
}
}
2.2.2.被观察者具体实现
/**
* 观察者设计模式案例:基于jdk提供的被观察者实现
* 业务场景描述:电商降价通知
* @author ThinkPad
* @version 1.0
* @date 2021/3/21 7:45
*/
public class ProductByJdk extends Observable{
// 商品名称
private String name;
// 商品价格
private float price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
/**
* 重点关注:当设置价格,即价格发生变化后,发出价格变更通知
* @param price
*/
public void setPrice(float price) {
this.price = price;
// 设置变化点
setChanged();
// 通知观察者
notifyObservers(new Float(price));
}
}
2.2.3.使用案例
public static void main(String[] args) {
// 创建观察者对象
ProductPriceObserverByJdk observer = new ProductPriceObserverByJdk();
// 创建被观察者(商品对象)
ProductByJdk product = new ProductByJdk();
// 添加观察者
product.addObserver(observer);
// 设置商品名称
product.setName("苹果手机");
// 设置商品价格(触发观察-被观察行为的执行)
product.setPrice(99.0f);
}
#执行结果
ProductPriceObserver观察到商品【苹果手机】价格更新为【99.0】.
Process finished with exit code 0