java设计模式:发布订阅模式(观察者模式)

设计模式两大原则:里式替换原则,将父类替换成子类一定可行;开闭原则:对修改关闭,对扩展开启

monitor也是被观察者Observable和事件发布者publisher。 监视器装在被观察的商店里 如果商品价格有变动,商场去通知消费者和工商局 消费者和工商局 。商场是被观察者是事件消息通知的发布者,工商局和消费者是观察者是事件通知消息的接受者。 观察者(Observer 有的叫监听者 listener在发布订阅模式中又叫订阅者 subcriber)用来接受通知信息。那么观察者接口用定义接受通知的事件函数(行为)。所以观察者类(实现观察者接口)中用来定义事件函数,观察者的具体实现可以定义事件的具体通知行为。这种形式的观察者模式:分两层即观察者和被观察者被观察者

Monitor也叫被观察者Observable 和事件发布者publisher,基本功能可以添加和删除观察者

package com.example.observer;

public interface ProductMonitor {
    void addObserver(ProductObserver observer);
    void removeObserver(ProductObserver observer);
}

例如spring boot源码ApplicationContext 就是一个被观察者和事件发布者。可以通知注册的监听者:The ability to publish events to registered listeners.

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver

ApplicationContext 通过public void publishEvent(Object event)方法会调用事件多播器根据事件的类型进行广播通知

AbstractApplicationEventMulticaster事件多播器 承担了将事件发布者ApplicationContext (被观察者) 和观察者(订阅者)ApplicationListener结合起来的作用,进行解耦。1.事件多播器可以将相关订阅者进行添加 2.事件多播器可以通知订阅者。从而实现发布和订阅的功能。

1.事件多播器可以将相关订阅者进行添加 如下代码

// AbstractApplicationEventMulticaster
@Override
	public void addApplicationListener(ApplicationListener<?> listener) {
		synchronized (this.retrievalMutex) {
			// Explicitly remove target for a proxy, if registered already,
			// in order to avoid double invocations of the same listener.
			Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
			if (singletonTarget instanceof ApplicationListener) {
				this.defaultRetriever.applicationListeners.remove(singletonTarget);
			}
			this.defaultRetriever.applicationListeners.add(listener);
			this.retrieverCache.clear();
		}
	}

2.事件多播器可以通知订阅者。相关代码如下:

// ApplicationContext执行发布 publishEvent方法最终会执行
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);

SimpleApplicationEventMulticaster 简单事件多播器继承了AbstractApplicationEventMulticaster

	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
				invokeListener(listener, event);
			}
		}
	}

invokeListener最终调的就是listener的onApplicationEvent方法

private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
		try {
			listener.onApplicationEvent(event);
		}
		catch (ClassCastException ex) {
			String msg = ex.getMessage();
			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
				// Possibly a lambda-defined listener which we could not resolve the generic event type for
				// -> let's suppress the exception and just log a debug message.
				Log logger = LogFactory.getLog(getClass());
				if (logger.isTraceEnabled()) {
					logger.trace("Non-matching event type for listener: " + listener, ex);
				}
			}
			else {
				throw ex;
			}
		}
	}

观察者接口/listener/subcriber,定义观察者满足触发条件时的动作(定义事件函数)

package com.example.observer;

public interface ProductObserver {

	void onEvent(Product product);

	void onPriceChanged(Product product);
}

有些观察者模式把通知变成一个Event对象,从而不再有多种方法通知,而是统一成一种:让观察者自己从Event对象中读取通知类型和通知数据。

public interface ProductObserver {
    void onEvent(ProductEvent event);
}

例如spring boot的源码:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

	/**
	 * Handle an application event.
	 * @param event the event to respond to
	 */
	void onApplicationEvent(E event);

}

public abstract class ApplicationEvent extends EventObject {

	/** use serialVersionUID from Spring 1.2 for interoperability. */
	private static final long serialVersionUID = 7099057708183571937L;

	/** System time when the event happened. */
	private final long timestamp;

	public ApplicationEvent(Object source) {
		super(source);
		this.timestamp = System.currentTimeMillis();
	}


	/**
	 * Return the system time in milliseconds when the event happened.
	 */
	public final long getTimestamp() {
		return this.timestamp;
	}

}

有些还将观察者Observer和观察者的事件(监听者)listener 进行分离类比c#的委托,比喻的话可以将观察者比作工商局 listener比喻成工商局的工商管理人员,工商管理人员去做具体的动作,监听者和观察者其实是一个单位的,这样一来,观察者Observer中可以添加监听者listener,监听者用来做具体的动作。这种形式的观察者模式分3层:被观察者monitor/Observable ,观察者Observer和监听者listener。向被观察者添加观察者 向观察者添加监听者

如下边源码

FileAlterationMonitor是被观察者

public final class FileAlterationMonitor implements Runnable {
    private final List<FileAlterationObserver> observers = new CopyOnWriteArrayList<>();
    }

    public void addObserver(final FileAlterationObserver observer) {
        if (observer != null) {
            observers.add(observer);
        }
    }

    public void removeObserver(final FileAlterationObserver observer) {
        if (observer != null) {
            while (observers.remove(observer)) {
                // empty
            }
        }
    }

观察者

public class FileAlterationObserver implements Serializable {

    private final List<FileAlterationListener> listeners = new CopyOnWriteArrayList<FileAlterationListener>();
    public void addListener(final FileAlterationListener listener) {
        if (listener != null) {
            listeners.add(listener);
        }
    }
    private void doDelete(FileEntry entry) {
        for (FileAlterationListener listener : listeners) {
            if (entry.isDirectory()) {
                listener.onDirectoryDelete(entry.getFile());
            } else {
                listener.onFileDelete(entry.getFile());
            }
        }
    }
}
// 监听者
public interface FileAlterationListener {

    /**
     * File system observer started checking event.
     *
     * @param observer The file system observer
     */
    void onStart(final FileAlterationObserver observer);

    /**
     * Directory created Event.
     * 
     * @param directory The directory created
     */
    void onDirectoryCreate(final File directory);

    /**
     * Directory changed Event.
     * 
     * @param directory The directory changed
     */
    void onDirectoryChange(final File directory);

    /**
     * Directory deleted Event.
     * 
     * @param directory The directory deleted
     */
    void onDirectoryDelete(final File directory);

    /**
     * File created Event.
     * 
     * @param file The file created
     */
    void onFileCreate(final File file);

    /**
     * File changed Event.
     * 
     * @param file The file changed
     */
    void onFileChange(final File file);

    /**
     * File deleted Event.
     * 
     * @param file The file deleted
     */
    void onFileDelete(final File file);

    /**
     * File system observer finished checking event.
     *
     * @param observer The file system observer
     */
    void onStop(final FileAlterationObserver observer);
}

类似这种结构

定义一个产品

package com.example.observer;

public class Product {

	private String name;
	private double price;

	public Product(String name, double price) {
		this.name = name;
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public double getPrice() {
		return price;
	}

	void setPrice(double price) {
		this.price = price;
	}

	@Override
	public String toString() {
		return String.format("{Product: name=%s, price=%s}", name, price);
	}
}

自己写的简单的小程序作为实例:
被观察者Store 添加观察者,发布事件通知

package com.example.observer;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Store implements ProductMonitor{

    private List<ProductObserver> observers = new CopyOnWriteArrayList<>();
    private Map<String, Product> products = new ConcurrentHashMap<>();
    ExecutorService threadPool=Executors.newFixedThreadPool(5);

   // 添加观察者
    public void addObserver(ProductObserver observer) {
        this.observers.add(observer);
    }

    public void removeObserver(ProductObserver observer) {
        this.observers.remove(observer);
    }

    public void addNewProduct(String name, double price) {
        Product p = new Product(name, price);
        products.put(p.getName(), p);
        // 发布消息 通知
//		observers.forEach(o -> o.onEvent(p));
		observers.forEach(o->{
			threadPool.execute(()->{
				o.onEvent(p);
			});
		});
    }

    public void setProductPrice(String name, double price) {
        Product p = products.get(name);
        p.setPrice(price);
//        observers.forEach(o -> o.onEvent(p));
        // 发布消息 通知
		observers.forEach(o->{
			threadPool.execute(()->{
				o.onPriceChanged(p);
			});
		});
    }
}

在客户端订阅(注册),观察者 Customer Admin 和匿名观察者

package com.example.observer;

public class Host {

    public static void main(String[] args) {
        // observer:
        Admin a = new Admin();
        Customer c = new Customer();
        // store:
        Store store = new Store();
        // register:
        store.addObserver(a);
        store.addObserver(c);
        // 注册匿名观察者:
        store.addObserver(new ProductObserver() {
            @Override
            public void onEvent(Product product) {
                System.out.println("[Log] on product published: " + product);
            }

            @Override
            public void onPriceChanged(Product product) {
                System.out.println("[Log] on product price changed: " + product);
            }
        });
        // operation:
        store.addNewProduct("Design Patterns", 35.6);
        store.addNewProduct("Effective Java", 50.8);
        store.setProductPrice("Design Patterns", 31.9);
    }
}

class Customer implements ProductObserver {

    @Override
    public void onEvent(Product product) {
        System.out.println("[Customer] on product published: " + product);
    }

    @Override
    public void onPriceChanged(Product product) {
        System.out.println("[Customer] on product price changed: " + product);
    }
}

class Admin implements ProductObserver {

    @Override
    public void onEvent(Product product) {
        System.out.println("[Admin] on product published: " + product);
    }

    @Override
    public void onPriceChanged(Product product) {
        System.out.println("[Admin] on product price changed: " + product);
    }
}

结果

[Customer] on product published: {Product: name=Design Patterns, price=35.6}
[Customer] on product published: {Product: name=Effective Java, price=50.8}
[Admin] on product published: {Product: name=Design Patterns, price=35.6}
[Admin] on product published: {Product: name=Effective Java, price=50.8}
[Log] on product published: {Product: name=Design Patterns, price=35.6}
[Admin] on product price changed: {Product: name=Design Patterns, price=31.9}
[Log] on product published: {Product: name=Effective Java, price=50.8}
[Log] on product price changed: {Product: name=Design Patterns, price=31.9}
[Customer] on product price changed: {Product: name=Design Patterns, price=31.9}

应用:监听文件变化

maven依赖

  <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
 </dependency>

自定义监听者的事件

package com.example.observerExample;

import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;

import java.io.File;

/**
 * 事件监听者:自定义监听者的事件
 */

public class MyFileListenerAdaptor extends FileAlterationListenerAdaptor {
    @Override
    public void onFileChange(File file) {
        System.out.println("change.............");
    }

    @Override
    public void onStart(FileAlterationObserver observer) {
        System.out.println("start");
    }

    @Override
    public void onStop(FileAlterationObserver observer) {
        System.out.println("stop");
    }

    @Override
    public void onDirectoryChange(File directory) {
        System.out.println("dir change.........");
    }

    @Override
    public void onDirectoryCreate(File directory) {
        System.out.println("dir create.........");
    }

    @Override
    public void onDirectoryDelete(File directory) {
        System.out.println("dir delete.........");
    }

}

为监视器添加观察者,并为观察者添加事件监听者

package com.example.observerExample;

import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;

public class MyFileAlterationMonitor {

    private String path;		// 文件夹目录

    private String fileSuffix;	// 需要监听的文件名后缀

    private long interval;		// 监听间隔

    private static final long DEFAULT_INTERVAL = 10 * 1000; // 默认监听间隔10s

    private FileAlterationListenerAdaptor listener;	// 事件处理类对象

    public MyFileAlterationMonitor(){
        this.interval = DEFAULT_INTERVAL;
    }

    public MyFileAlterationMonitor(String path, String fileSuffix, FileAlterationListenerAdaptor listenerAdaptor){
        this.path = path;
        this.fileSuffix = fileSuffix;
        this.interval = DEFAULT_INTERVAL;
        this.listener = listenerAdaptor;
    }

    public MyFileAlterationMonitor(String path, String fileSuffix, long interval, FileAlterationListenerAdaptor listenerAdaptor) {
        this.path = path;
        this.fileSuffix = fileSuffix;
        this.interval = interval;
        this.listener = listenerAdaptor;
    }

    /***
     * 开启监听
     */
    public void start() {
        if(path==null) {
            throw new IllegalStateException("Listen path must not be null");
        }
        if(listener==null) {
            throw new IllegalStateException("Listener must not be null");
        }
        // FileAlterationMonitor本身实现了 Runnable
        FileAlterationMonitor monitor = new FileAlterationMonitor(interval);

        // 设定观察者,监听.properties文件
        FileAlterationObserver observer = new FileAlterationObserver(path,
                FileFilterUtils.suffixFileFilter(fileSuffix));

        monitor.addObserver(observer);

        // 给观察者添加监听事件
        observer.addListener(listener);

        try {
            monitor.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void setPath(String path) {
        this.path = path;
    }

    public void setFileSuffix(String fileSuffix) {
        this.fileSuffix = fileSuffix;
    }

    public void setAdaptor(FileAlterationListenerAdaptor listenerAdaptor) {
        this.listener = listenerAdaptor;
    }

}

Main方法

package com.example.observerExample;


public class Test {
    public static void main(String[] args) {
        String path=Test.class.getClassLoader().getResource("").getPath();
        System.out.println(path);
        MyFileAlterationMonitor monitor = new MyFileAlterationMonitor(
                path,
                "",
                new MyFileListenerAdaptor());
        monitor.start();
    }

}

结果:文件改变时结果变化如下
stop
start
stop
start
change…
stop

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java的观察者设计模式是一种一对多的依赖关系,其中目标对象维护一组观察者对象,当目标对象的状态发生变化时,它会自动通知并更新所有的观察者对象。这种模式可以使目标对象与观察者对象之间解耦,使它们可以独立地进行修改和重用。 在Java中,观察者模式已经被封装成了两个接口:目标接口(Observable)和观察者接口(Observer)。目标接口(Observable)定义了添加、删除和通知观察者对象的方法,而观察者接口(Observer)定义了观察者对象接收更新通知的方法。 在实际应用中,我们可以通过实现观察者接口(Observer)来创建具体的观察者对象,并通过实现目标接口(Observable)来创建具体的目标对象。具体的观察者对象可以订阅目标对象的状态变化,并根据变化做出相应的响应。 在Java中,观察者模式被广泛应用于各个领域。在Android开发中,许多常见的组件和框架都使用了观察者模式,比如OnClickListener、ContentObserver,以及RxJava、RxAndroid和EventBus等通讯库。这些例子都是基于观察者模式的实现,通过观察者模式可以实现组件之间的解耦和灵活的消息传递。 总结来说,Java的观察者设计模式是一种实现目标和观察者对象之间解耦的设计模式,它可以提高代码的灵活性和可维护性。在实际应用中,我们可以使用Java提供的目标接口(Observable)和观察者接口(Observer)来实现观察者模式,并通过具体的观察者对象订阅目标对象的状态变化。这种设计模式在Android开发中也被广泛应用,并带来了许多便利的消息传递和通讯方式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Java设计模式观察者模式(Observer Pattern)](https://blog.csdn.net/engineer_zh/article/details/78857166)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [java设计模式观察者模式](https://blog.csdn.net/m0_47944994/article/details/127903096)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值