定义
多个对象之前存在一对多的依赖关系,当一个对象的状态发生了改变时,所有依赖于它的对象都得到通知并自动更新,又称为发布——订阅模式
优点:
降低目标与观察者间的耦合关系,在目标和观察者模式之间建立了一套触发机制
缺点:
目标和观察者之间的依赖关系并未完全解除,而且可能循环使用,当观察者对象很多时,通知的发布会花费很多时间。
实例
下面是用观察者模式模拟股票两个不同持有者(抛售方,购买方)关注角度,话不多说,上代码:
package obs;
import java.util.ArrayList;
import java.util.List;
public abstract class AStockPrice {
protected float price,price2;//现价,原价
public float getPrice2() {
return price2;
}
public void setPrice2(float price2) {
this.price2 = price2;
}
protected String code;//区分对象,code相同则认为是同一种股票
protected List<IStockHolder>stockHolderlist;//观察者种类
public void Add(IStockHolder Ish) {
stockHolderlist.add(Ish);
}
public void Remove(IStockHolder Ish) {
stockHolderlist.remove(Ish);
}
public AStockPrice(String code) {
this.code=code;
price=price2=0;
stockHolderlist=new ArrayList<IStockHolder>();
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
notifyHolder();
}
//不同的股票种类有不同类型的通知
abstract protected void notifyHolder();
//代码生成器自动生成,保留code,去掉price进行区分。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((code == null) ? 0 : code.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AStockPrice other = (AStockPrice) obj;
if (code == null) {
if (other.code != null)
return false;
} else if (!code.equals(other.code))
return false;
return true;
}
}
package obs;
/*
* 股票持有者抽象接口
*/
public interface IStockHolder {
public void update(AStockPrice asp);
public void AddHolder(AStockPrice asp);
}
package obs;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Administrator
* 买方
*
*/
public class BuyHolder implements IStockHolder {
private List<AStockPrice>attentionList;
private String name;
public BuyHolder(String name) {
attentionList=new ArrayList<AStockPrice>();
this.name=name;
}
@Override
public void update(AStockPrice asp) {
// TODO Auto-generated method stub
if(attentionList.contains(asp)) {
System.out.println(name);
if(asp.getPrice()-asp.getPrice2()>0) {
System.out.println(asp.code+":");
System.out.println("原价:"+asp.price2+"现价:"+asp.price);
System.out.println("涨了,爽!");
}
else {
System.out.println(asp.code+":");
System.out.println("原价:"+asp.price2+"现价:"+asp.price);
System.out.println("跌了,哭!");
}
}
}
@Override
public void AddHolder(AStockPrice asp) {
// TODO Auto-generated method stub
attentionList.add(asp);
asp.Add(this);
}
}
package obs;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Administrator
*抛售方
*/
public class SellHolder implements IStockHolder {
private List<AStockPrice>attentionList;
private String name;
public SellHolder(String name) {
// TODO Auto-generated constructor stub
attentionList=new ArrayList<AStockPrice>();
this.name=name;
}
@Override
public void update(AStockPrice asp) {
// TODO Auto-generated method stub
if(attentionList.contains(asp)) {
System.out.println(name);
if(asp.getPrice()-asp.getPrice2()>0) {
System.out.println(asp.code+":");
System.out.println("原价:"+asp.price2+"现价:"+asp.price);
System.out.println("涨了,哭!");
}
else {
System.out.println(asp.code+":");
System.out.println("原价:"+asp.price2+"现价:"+asp.price);
System.out.println("跌了,爽!");
}
}
}
@Override
public void AddHolder(AStockPrice asp) {
// TODO Auto-generated method stub
attentionList.add(asp);
asp.Add(this);
}
}
package obs;
/**
* 期货
* @author Administrator
*
*/
public class StockFutures extends AStockPrice {
public StockFutures(String code) {
super(code);
// TODO Auto-generated constructor stub
}
@Override
protected void notifyHolder() {
// TODO Auto-generated method stub
System.out.println("期货更新了——"+code+":");
for(IStockHolder ish:stockHolderlist) {
//System.out.println(ish);
ish.update(this);
}
price2=price ;
}
}
package obs;
/**
* 普通股票
* @author Administrator
*
*/
public class StockCommon extends AStockPrice {
public StockCommon(String code) {
super(code);
// TODO Auto-generated constructor stub
}
@Override
protected void notifyHolder() {
// TODO Auto-generated method stub
System.out.println("普通股票更新了——"+code+":");
for(IStockHolder ish:stockHolderlist) {
ish.update(this);
}
price2=price;
}
}
package obs;
public class ClientClass {
public static void main(String[] args) {
// TODO Auto-generated method stub
AStockPrice future1=new StockFutures("111");
AStockPrice future2=new StockFutures("222");
AStockPrice future3=new StockFutures("333");
//
// future1.setPrice(50);
// future1.setPrice2(80);
// future2.setPrice(70);
// future2.setPrice2(55);
// future3.setPrice(90);
// future3.setPrice2(80);
AStockPrice common5=new StockCommon("555");
AStockPrice common6=new StockCommon("666");
AStockPrice common7=new StockCommon("777");
// common5.setPrice(77);
// common5.setPrice2(60);
// common6.setPrice(66);
// common6.setPrice2(90);
// common7.setPrice(78);
// common7.setPrice2(80);
IStockHolder Buy1=new BuyHolder("Buy1");
IStockHolder Buy2=new BuyHolder("Buy2");
IStockHolder Buy3=new BuyHolder("Buy3");
IStockHolder sell1=new SellHolder("sell1");
IStockHolder sell2=new SellHolder("sell2");
IStockHolder sell3=new SellHolder("sell3");
Buy1.AddHolder(future1);
Buy1.AddHolder(future2);
Buy1.AddHolder(common5);
Buy2.AddHolder(future1);
Buy2.AddHolder(future3);
Buy2.AddHolder(common6);
Buy3.AddHolder(future3);
Buy3.AddHolder(future2);
Buy3.AddHolder(common7);
sell1.AddHolder(future1);
sell1.AddHolder(future3);
sell1.AddHolder(common6);
sell2.AddHolder(future1);
sell2.AddHolder(future2);
sell2.AddHolder(common5);
sell3.AddHolder(future3);
sell3.AddHolder(future2);
sell3.AddHolder(common7);
for(int i=0;i>-5;i--) {
future1.setPrice(1+i);
future2.setPrice(1+i);
future3.setPrice(1+i);
common5.setPrice(1+i);
common6.setPrice(1+i);
common7.setPrice(1+i);
}
}
}
运行结果:
注意程序关键代码部分:
股票的价格变动就去提醒买方和卖方。 在客户端调用时,应该先生成持有者对象再去设置价格,否则通知的对象列表为空,无法获得预期结果。
学习视频指路:黑手书生
https://www.bilibili.com/video/av95698793?from=search&seid=5012547147156938065