【设计模式-4.2】行为型——观察者模式

说明:本文介绍设计模式中行为型设计模式中的,观察者模式;

商家与顾客

观察者模式属于行为型设计模式,关注对象的行为。以商家与顾客为例,商家有商品,顾客来购买商品,如果商家商品卖完了,顾客则购买失败。如下:

(Shop,商家类,提供购买、进货方法)

/**
 * 商家
 */
public class Shop {
    
    

    /**
     * 商品
     */
    private String product;

    public Shop() {
    
    
        this.product = "无商品";
    }

    /**
     * 出货
     * @return
     */
    public String getProduct() {
    
    
        return product;
    }

    /**
     * 进货
     * @param product
     */
    public void setProduct(String product) {
    
    
        this.product = product;
    }
}

(Buyer,顾客类,注入商店对象,购买商店商品)

/**
 * 顾客
 */
public class Buyer {
    
    

    private String name;

    private Shop shop;

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

    /**
     * 买家购买商品
     */
    public void buy() {
    
    
        System.out.println(name + "来购买:" + shop.getProduct());
    }
}

(Client,客户端,演示购买动作)

/**
 * 客户端
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Shop shop = new Shop();
        new Buyer("张三", shop).buy();

        shop.setProduct("橘子");
        new Buyer("李四", shop).buy();
    }
}

(执行结果)

在这里插入图片描述

分析上面的行为,可以发现一点缺陷。当商家的商品发生变化时,无法主动的,自发的通知顾客,只有顾客来购买时,才知道商品的信息。因此,我们考虑是否可以在商家类内部维护一个“顾客列表”,当商品信息发生变化时,调用顾客列表中所有顾客对应的方法,达到主动通知客户的目的。如下:

(Shop,商家类,维护一个顾客列表,新增一个通知顾客的方法)

import java.util.ArrayList;
import java.util.List;

/**
 * 商家
 */
public class Shop {
    
    

    /**
     * 商品
     */
    private String product;

    /**
     * 顾客列表
     */
    private List<Buyer> buyers;

    public Shop() {
    
    
        this.product = "无商品";
        this.buyers = new ArrayList<>();
    }

    /**
     * 添加顾客
     * @param buyer
     */
    public void addBuyer(Buyer buyer) {
    
    
        this.buyers.add(buyer);
    }
    
    /**
     * 移除顾客
     * @param buyer
     */
    public void removeBuyer(Buyer buyer) {
    
    
        this.buyers.remove(buyer);
    }

    /**
     * 出货
     * @return
     */
    public String getProduct() {
    
    
        return product;
    }

    /**
     * 进货
     * @param product
     */
    public void setProduct(String product) {
    
    
        this.product = product;
        notifyBuyers();
    }

    /**
     * 通知顾客
     */
    public void notifyBuyers() {
    
    
        for (Buyer buyer : buyers) {
    
    
            buyer.buy(product);
        }
    }
}

(Buyer,顾客抽象类,创建一个购买商品的抽象方法)

/**
 * 顾客
 */
public abstract class Buyer {
    
    

    /**
     * 顾客姓名
     */
    protected String name;

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

    /**
     * 买家购买商品
     */
    public abstract void buy(String product);
}

(FruitBuyer,水果买家,只购买水果类的商品)

/**
 * 水果买家
 */
public class FruitBuyer extends Buyer{
    
    

    public FruitBuyer(String name) {
    
    
        super(name);
    }

    @Override
    public void buy(String product) {
    
    
        if (product.contains("水果")) {
    
    
            System.out.println(name + ":来购买了水果");
        }
    }
}

(PhoneBuyer,手机买家,只购买手机类的商品)

/**
 * 手机买家
 */
public class PhoneBuyer extends Buyer{
    
    

    public PhoneBuyer(String name) {
    
    
        super(name);
    }

    @Override
    public void buy(String product) {
    
    
        if (product.contains("手机")) {
    
    
            System.out.println(name + ":来购买了手机");
        }
    }
}

(Client,客户端,模拟购买行为,张三只购买手机,买了一次后就不再需要了)

/**
 * 客户端
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Shop shop = new Shop();
        PhoneBuyer phoneBuyer = new PhoneBuyer("张三");
        FruitBuyer fruitBuyer = new FruitBuyer("李四");

        shop.addBuyer(phoneBuyer);
        shop.addBuyer(fruitBuyer);

        shop.setProduct("苹果手机");
        shop.setProduct("各种水果");
        shop.removeBuyer(phoneBuyer);

        System.out.println("=================水果和手机降价了=================");
        shop.setProduct("水果和手机降价了");

    }
}

执行结果。当商家的商品信息有变化时,会通知到对应的顾客来购买。

在这里插入图片描述

类比现实生活,小村庄里只有一家商店。我们需要购买某样日用品,去商店购买,店长说没有,下个月才进货。很自然的,我们会和店长说,那我留下电话,进货了打电话通知我。

其中,留下电话,可以类比为将顾客注册到商店类中,而打电话则是调用顾客类对应的方法。

Spring中的体现

观察者模式,是一种订阅-发布的模式。在上面的例子中,商家是发布者,顾客是订阅者,当商家商品信息有变动时,发布信息,顾客接收。

Spring框架中,就有观察者模式的应用。如下:

(Customer,消费者类)

import org.springframework.context.ApplicationEvent;

public class Customer extends ApplicationEvent {
    
    

    private String message;

    public Customer(Object source, String message) {
    
    
        super(source);
        this.message = message;
    }


    public String getMessage() {
    
    
        return message;
    }
}

(CustomListener1,消费者1号)

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class CustomListener1 implements ApplicationListener<Customer> {
    
    

    @Override
    public void onApplicationEvent(Customer customer) {
    
    
        System.out.println("1号订阅者收到消息: " + customer.getMessage());
    }
}

(CustomListener2,消费者2号)

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class CustomListener2 implements ApplicationListener<Customer> {
    
    

    @Override
    public void onApplicationEvent(Customer customer) {
    
    
        System.out.println("2号订阅者收到消息: " + customer.getMessage());
    }
}

(Publisher,发布者)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

@Component
public class Publisher {
    
    

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void publishCustomEvent(String message) {
    
    
        eventPublisher.publishEvent(new Customer(this, message));
    }
}

(在测试类中,发布信息)

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class PublisherTest {
    
    

    @Autowired
    private Publisher publisher;

    @Test
    public void test1() {
    
    
        publisher.publishCustomEvent("Hello World!");
    }
}

执行结果,2个订阅者都收到了消息;

在这里插入图片描述

以上就是观察者模式的实现;

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

猜你喜欢

转载自blog.csdn.net/qq_42108331/article/details/134765672