1.定义
对象之间的一种一对多的依赖关系,其中的一个对象状态发生了变化,依赖中其他相关的对象接收到了通知并自动更新。
2.案例
Sunny软件公司欲开发一款实时在线股票软件,该软件需提供如下功能:当股票购买者所购买的某支股票价格变化幅度达到5%时,系统将自动发送通知(包括新价格)给购买该股票的所有股民。试使用观察者模式设计并实现该系统。
2.1 UML
2.2 代码
/**
* @ClassName Launcher
* @Description: 启动类(观察者模式)
* @Author cw
* @Date 2020/3/2
**/
public class Launcher {
/**
* Sunny软件公司欲开发一款实时在线股票软件,
* 该软件需提供如下功能:当股票购买者所购买的某支股票价格变化幅度达到5%时,
* 系统将自动发送通知(包括新价格)给购买该股票的所有股民。
* 试使用观察者模式设计并实现该系统。
* @param args
*/
public static void main(String[] args) {
StockObserver stockA = new StockObserver("001", "A股票",new BigDecimal(1.1));
StockObserver stockB = new StockObserver("002", "B股票",new BigDecimal(2));
Buyer buyerA = new Buyer("唐僧");
Buyer buyerB = new Buyer("悟空");
Buyer buyerC = new Buyer("八戒");
Control control = new StockMarketControl();
control.attach(stockA.getKey(), buyerA);
control.attach(stockA.getKey(), buyerC);
control.attach(stockB.getKey(), buyerA);
control.attach(stockB.getKey(), buyerB);
stockA.change(control,new BigDecimal(-0.05));
}
}
/**
* 抽象观察类(股票)
*/
interface Observer {
public void change(Control control, BigDecimal percent);//变化具体数值
}
/**
* 具体观察类(股票)
*/
class StockObserver implements Observer {
private String key;//股票唯一编码
private String name;//股票名称
private BigDecimal price;//股票价格
public StockObserver(String key, String name,BigDecimal price) {
this.key = key;
this.name = name;
this.price = price;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
@Override
public void change(Control control, BigDecimal percent) {
control.publish(this, percent);
}
}
/**
* 购买者类
*/
class Buyer {
private String name;//购买者
public Buyer(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void receive(StockObserver stock,BigDecimal floatRate) {
System.out.println(name + "接收;股票【" + stock.getName() + "】浮动价格【"+(stock.getPrice().multiply(floatRate)).setScale(2, BigDecimal.ROUND_HALF_UP)+"】");
}
}
/**
* 抽象控制类
*/
abstract class Control {
Map<String, List<Buyer>> mapStock = new HashMap<>();
public void attach(String key, Buyer buyer) {
List<Buyer> listBuyer = mapStock.get(key);
if (listBuyer == null) {
listBuyer = new ArrayList<>();
listBuyer.add(buyer);
mapStock.put(key, listBuyer);
} else {
listBuyer.add(buyer);
}
}
public abstract void publish(StockObserver stock, BigDecimal percent);
}
/**
* 具体控制类(股市)
*/
class StockMarketControl extends Control {
@Override
public void publish(StockObserver stock, BigDecimal percent) {
if (percent.compareTo(new BigDecimal(0.05)) < 0 && percent.compareTo(new BigDecimal(-0.05)) > 0){
System.out.println("股票:" + stock.getName() + ";涨幅没有到达5%,不进行通知");
return;
}
List<Buyer> lstBuyer = mapStock.get(stock.getKey());
if (lstBuyer == null) {
System.out.println("股票:" + stock.getName() + ";暂时没人购买");
return;
}
lstBuyer.forEach(item -> {
item.receive(stock,percent);
});
}
}