观察者模式

0.前言

有人把观察者(Observer)模式等同于发布(Publish)/订阅(Subscribe)模式,也有人认为这两种模式还是存在差异,但总体来说差异并不大。

实际生活中,发布/订阅模式较为常见,接触比较多的是会员用户扫码关注了某店铺微信小程序。比如说:

​ A同学关注了 李宁运动店铺

​ B同学关注了 必胜客披萨店

​ C同学则两家都关注了

于是,当球鞋换季时,A和C可以收到李宁店铺的广告;Pizza出新品菜单,B和C又可以收到推荐及时尝鲜。

1.店铺类

店铺必须具备2个功能:

1.持有会员,方面后期管理,得知道哪些客户关注了店铺

2.店铺得发布通知,告知会员

创建抽象类 Shop

/** 
 * Shop 普通店铺 
 *
 * @author: 喵掌柜 
 */
public abstract class Shop {
    
    // 持有的顾客列表
    private List<Customer> customerList = new ArrayList<>();
    
    /** 发布内容 */
    public void notify(String messageStr) {
        // 待实现    
    }
}

使用 private 修饰 customerList,表示 客户信息是店铺的内部数据,不会暴漏给外部的

2.客户类

客户需要具有订阅能力,获得店铺最新消息

/**
 * Customer
 *
 * @author: 喵掌柜
 */
public abstract class Customer {

    /** 订阅某店铺 */
    public void subscribe(Shop shop){
        // 待实现
    }

    /** 阅读来自某店铺的推广、通知  */
    public void getMessage(Shop shop){
        // 待实现
    }
}

3.完善订阅

店铺类 Shop 需要一个接口方法(可类比于二维码),帮助客户 Customer 完成订阅

    /** Shop 类订阅方法 */
    public void attach(Customer... customers) {
        for (Customer customer : customers) {
            customerList.add(customer);
        }
    }

客户 Customer 完成订阅方法

    /** Customer 订阅某店铺 */
    public void subscribe(Shop shop){
        shop.attach(this);
    }

4.完善发布

店铺类 Shop 的通知方法,店员会使用它发布新通知

    /** Shop 发布内容 */
    public void notify(String messageStr) {
        // 把消息逐一发送给订阅的客户
        customerList.forEach(customer -> {
            customer.getMessage(messageStr);
        });
    }

订阅的客户拿到消息后,直接打印到屏幕上就行

    /** Customer 阅读来自某店铺的推广、通知  */
    public void getMessage(String message){
        // 正常打印即可
        System.out.println(message);
    }

5.其他完善

给店铺、顾客都起个名字吧,好分辨,完整的如下:

public abstract class Shop {

    private String name;

    public Shop(String name){
        this.name = name;
    }

    // 持有得顾客列表
    private List<Customer> customerList = new ArrayList<>();

    /** 订阅方法 */
    public void attach(Customer... customers) {
        for (Customer customer : customers) {
            customerList.add(customer);
        }
    }

    /** 发布内容 */
    public void notify(String messageStr) {
    // 把消息逐一发送给订阅用户
    customerList.forEach(
        customer -> {
          System.out.println("消息来自:" + this.name);
          customer.getMessage(messageStr);
        });
    }

}

李宁和披萨店

public class LiNingShop extends Shop{

    public LiNingShop() {
        super("LiNing");
    }
}

public class PizzaShop extends Shop{

    public PizzaShop() {
        super("Pizza");
    }
}

顾客类

@Data
@AllArgsConstructor
public class Customer {

    private String name;

    /** 订阅某店铺 */
    public void subscribe(Shop shop){
        shop.attach(this);
    }

    /** 阅读来自某店铺的推广、通知  */
    public void getMessage(String message){
        // 正常打印即可
        System.out.println("接收者:" + this.name);
        System.out.println("消息内容:" + message);
        System.out.println("##########################");
    }

}

6.main方法以及结果

    public static void main(String[] args) {
        LiNingShop liNingShop = new LiNingShop();
        PizzaShop pizzaShop = new PizzaShop();

        Customer customerA = new Customer("小A");
        Customer customerB = new Customer("小B");
        Customer customerC = new Customer("小C");

        // A、C订阅李宁店
        customerA.subscribe(liNingShop);
        customerC.subscribe(liNingShop);

        // B、C订阅披萨店
        customerB.subscribe(pizzaShop);
        customerC.subscribe(pizzaShop);

        // 各个店铺发布变更消息
        liNingShop.notify("新款运动鞋到货");
        pizzaShop.notify("pizza推出美味新品");
    }

结果,A、C收到李宁店的消息,B、C收到pizza店的消息

消息来自:LiNing
接收者:小A
消息内容:新款运动鞋到货
##########################
消息来自:LiNing
接收者:小C
消息内容:新款运动鞋到货
##########################
消息来自:Pizza
接收者:小B
消息内容:pizza推出美味新品
##########################
消息来自:Pizza
接收者:小C
消息内容:pizza推出美味新品
##########################
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值