初探设计形式之【观察者】

一、前言

在现实生活中,观察者往往是主动的、被观察者是被动的。比如,要小王要向领导报告一件工作,因此时间重视着领导的工位,看领导有没有来公司。假如领导一向不来,关于小王来说,可能有点烦,这领导也太不省心了…..。咱们可以这么做,小王事先与领导沟通,然后领导告诉小王说:”今天会晚一些,到公司了会告诉你“,那这样,小王就省心多了,不用一向盯着这件事。

相应的,在软件开发中,也有类似的场景,比如在电商业务中,用户想要购买某件产品,但是产品暂时无货了,着急的用户可能会每隔一个小时跑来这个产品的页面改写,看是不是有货了,这就是一种观察者的主动行为,服务器作为被观察者是被动的,假如在大促期间这么做的用户非常多,不只用户体会不好,服务器还要接受特别大的压力,对两边都不好。而假如产品司理在商详中增加了【订阅到货】功用(想购买的用户点击订阅产品到货告诉,代产品到货后,告诉所有订阅者),就可以解决这些弊端了。

二、完成

首先是观察者基类:

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台苹果手机

剁手党:苹果手机现已被抢购一空

读书人买走了一本书:追风筝的人

剁手党买了一个书:追风筝的人

剁手党买了一个大白菜

三、总结

初探设计模式之【观察者】

作为一种发布/订阅式模型,观察者形式被很多应用于具有一对多关系对象结构的场景,它支持多个观察者订阅一个方针主题。一旦方针主题的状况发生变化,方针对象便主动进行广播,立刻对所有订阅者发布全员消息告诉。