初探设计形式之【观察者】
一、前言
在现实生活中,观察者往往是主动的、被观察者是被动的。比如,要小王要向领导报告一件工作,因此时间重视着领导的工位,看领导有没有来公司。假如领导一向不来,关于小王来说,可能有点烦,这领导也太不省心了…..。咱们可以这么做,小王事先与领导沟通,然后领导告诉小王说:”今天会晚一些,到公司了会告诉你“,那这样,小王就省心多了,不用一向盯着这件事。
相应的,在软件开发中,也有类似的场景,比如在电商业务中,用户想要购买某件产品,但是产品暂时无货了,着急的用户可能会每隔一个小时跑来这个产品的页面改写,看是不是有货了,这就是一种观察者的主动行为,服务器作为被观察者是被动的,假如在大促期间这么做的用户非常多,不只用户体会不好,服务器还要接受特别大的压力,对两边都不好。而假如产品司理在商详中增加了【订阅到货】功用(想购买的用户点击订阅产品到货告诉,代产品到货后,告诉所有订阅者),就可以解决这些弊端了。
二、完成
首先是观察者基类:
public abstract class Buyer {
private String name;
public Buyer(String name) {
this.name = name;
}
public String getName() {
return name;
}
public abstract void inform(Product product);
}
观察者的中心办法是一个抽象的告诉办法,统一被观察者告诉观察者的方式。
产品类:
public class Product {
public String name;
public int count;
public Product() {
}
public Product(String name, int count) {
this.name = name;
this.count = count;
}
}
然后咱们完成一些观察者,这里是具体的买家
手机黄牛:(遇见手机,有多少买多少)
/**
* 黄牛 专门倒卖手机 有多少收多少
*/
public class Vendor extends Buyer {
public Vendor(String name) {
super(name);
}
@Override
public void inform(Product product) {
if (product.name.contains("手机")) {
if (product.count > 0) {
System.out.println(getName() + "买光了" + product.count + "台" + product.name);
product.count = 0;
} else {
System.out.println(getName() + ":" + product.name + "现已被抢购一空");
}
}
}
}
手机爱好者:
public class PhoneBuyer extends Buyer {
public PhoneBuyer(String name) {
super(name);
}
@Override
public void inform(Product product) {
if (product.name.contains("手机")) {
if (product.count > 0) {
product.count--;
System.out.println(getName() + "买了一台" + product.name);
} else {
System.out.println(getName() + ":" + product.name + "现已被抢购一空");
}
}
}
}
爱读书的人:
public class Reader extends Buyer {
public Reader(String name) {
super(name);
}
@Override
public void inform(Product product) {
if (product.name.contains("书")) {
if (product.count > 0) {
product.count--;
System.out.println(getName() + "买走了一本" + product.name);
} else {
System.out.println(getName() + ":" + product.name + "现已被抢购一空");
}
}
}
}
购物狂,什么都买
public class Shopaholic extends Buyer {
public Shopaholic(String name) {
super(name);
}
@Override
public void inform(Product product) {
if (product.count > 0) {
product.count--;
System.out.println(getName() + "买了一个" + product.name);
} else {
System.out.println(getName() + ":" + product.name + "现已被抢购一空");
}
}
}
商铺类:
public class Shop {
private final List<Buyer> buyers = new ArrayList<>();
private Product product;
public void register(Buyer buyer) {
if (!buyers.contains(buyer)) {
buyers.add(buyer);
}
}
public void unRegister(Buyer buyer) {
buyers.remove(buyer);
}
public void setProduct(Product product) {
this.product = product;
notifyBuyers();
}
private void notifyBuyers() {
for (Buyer buyer : buyers) {
buyer.inform(product);
}
}
}
商铺类保护了一个买家列表,产品到货后,告诉所有买家,化被动为主动。
最后是调用处:
public static void main(String[] args) {
Shop shop = new Shop();
shop.register(new PhoneBuyer("果粉"));
shop.register(new Reader("读书人"));
shop.register(new Vendor("黄牛党"));
shop.register(new Shopaholic("剁手党"));
shop.setProduct(new Product("苹果手机", 100));
System.out.println("==============");
shop.setProduct(new Product("书:追风筝的人", 5));
System.out.println("==============");
shop.setProduct(new Product("大白菜", 100));
}
输入日志如下:
果粉买了一台苹果手机
黄牛党买光了99台苹果手机
剁手党:苹果手机现已被抢购一空
读书人买走了一本书:追风筝的人
剁手党买了一个书:追风筝的人
剁手党买了一个大白菜
三、总结
作为一种发布/订阅式模型,观察者形式被很多应用于具有一对多关系对象结构的场景,它支持多个观察者订阅一个方针主题。一旦方针主题的状况发生变化,方针对象便主动进行广播,立刻对所有订阅者发布全员消息告诉。