java设计模式--观察者模式

观察者模式定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
观察者:Observer update()
被观察者(目标):Subject attach();Detach();notify()
1. 目标与观察者的关系:典型的一对多
2. 单向依赖:
3. 命名建议
4. 触发通知的时机:完成消息处理后触发通知
5. 观察者模式的调用顺序:创建目标对象,创建观察者对象,向目标对象注册观察者对象—>
改变目标对象的状态,通知所有被注册的观察者对象进行相应的处理
回调目标对象,获取相应的数据。
6. 通知的顺序:多个观察者互相平行,通知先后也都是平行的。

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

/**
 * Created by dell on 2018/4/16.
 * 天气目标对象,它知道有谁观察了它,并提供注册(添加)和删除观察者的接口
 */
public class WeatherSubject {
    //用来保存注册的观察者对象
    private List<WeatherObserver> observers = new ArrayList<>();
    //attach 添加需要保存的观察者
    //添加订阅天气信息的人
    public void attach(WeatherObserver observer){
        observers.add(observer);
    }
    //detach 删除之前保存的观察者
    //删除集合中的指定了的订阅天气的人
    public void detach(WeatherObserver observer){
        observers.remove(observer);
    }
    //notifyObservers 通知所有注册的观察者对象
    //把更新了的天气信息通知所有已经订阅天气信息的人
    protected void notifyObservers(){
        for (WeatherObserver observer:observers){
            observer.update(this);
        }
    }
}
/**
 * 具体的目标对象,负责把有关状态存入到相应的观察者对象中
 * Created by dell on 2018/4/16.
 */
public class ConcreteWeatherSubject extends WeatherSubject {
    //目标对象的状态 获取天气信息
    private String weatherContent;

    public String getWeatherContent() {
        return weatherContent;
    }

    public void setWeatherContent(String weatherContent) {
        this.weatherContent = weatherContent;
        //天气已经更新,通知订阅者更新天气
        notifyObservers();
    }
}
/**
 * Created by dell on 2018/4/16.
 * 观察者接口,定义更新的方法,给那些在目标发生改变时,需要被通知的对象
 */
public interface WeatherObserver {
    /**
     * 更新的接口 subject
     * */
    public void update(WeatherSubject subject);
}
import java.util.Observer;

/**
 * 具体的观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致
 * Created by dell on 2018/4/16.
 */
public class ConcreteWeatherObserver implements WeatherObserver {

    //观察者的名字
    private String observerName;
    //天气情况内容 从subject中获取
    private String weatherContent;
    // 提醒的内容
    private String remindMsg;
    //获取目标类的状态同步到观察者的状态中
    @Override
    public void update(WeatherSubject subject) {
        weatherContent = ((ConcreteWeatherSubject)subject).getWeatherContent();
        System.out.println(observerName+"收到了"+weatherContent+","+remindMsg);
    }

    public String getObserverName() {
        return observerName;
    }

    public void setObserverName(String observerName) {
        this.observerName = observerName;
    }

    public String getWeatherContent() {
        return weatherContent;
    }

    public void setWeatherContent(String weatherContent) {
        this.weatherContent = weatherContent;
    }

    public String getRemindMsg() {
        return remindMsg;
    }

    public void setRemindMsg(String remindMsg) {
        this.remindMsg = remindMsg;
    }
}
public class Main {

    public static void main(String[] args) {
        //创建目标
        ConcreteWeatherSubject weather = new ConcreteWeatherSubject();
        //创建观察者
        ConcreteWeatherObserver girl = new ConcreteWeatherObserver();
        girl.setObserverName("喜欢逛街的女生");
        girl.setRemindMsg("天气晴朗,可以逛街");
        ConcreteWeatherObserver farmer = new ConcreteWeatherObserver();
        farmer.setObserverName("等待下雨的农民");
        farmer.setRemindMsg("天又晴了,快下雨吧");
        //注册观察者
        weather.attach(girl);
        weather.attach(farmer);
        //目标更新 观察者收到消息
        weather.setWeatherContent("天气晴朗");
    }
}

运行结果
喜欢逛街的女生收到了天气晴朗,天气晴朗,可以逛街
等待下雨的农民收到了天气晴朗,天又晴了,快下雨吧

Process finished with exit code 0

JDK提供的观察者模式
java.util.Observerable类和Observer接口
触发通知的方式:调用setChanged方法。
场景:有三位订阅者订阅了作家张三的博客。博客更新后会给订阅者发送消息,提醒订阅者去查看新的内容

import java.util.Observable;
import java.util.Observer;

/**
 * Created by dell on 2018/4/17.
 * 观察者/订阅者 实现Observer接口
 */
public class BlogReader implements Observer {
    private String BlogReaderName;

    public String getBlogReaderName() {
        return BlogReaderName;
    }

    public void setBlogReaderName(String blogReaderName) {
        BlogReaderName = blogReaderName;
    }

    private String BlogContent;

    public String getBlogContent() {
        return BlogContent;
    }

    public void setBlogContent(String blogContent) {
        BlogContent = blogContent;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println(getBlogReaderName()+"收到了博客更新消息,获得内容"+arg);

    }
    public void update(Observable o) {

        System.out.println(getBlogReaderName()+"主动查看作者"
                +(((Blog)o).getAuthorName()+"的更新内容"+((Blog)o).getBlogContent()));
    }
}

import java.util.Observable;
/**
 * Created by dell on 2018/4/17.
 * 博客类 可以向订阅者发布更新 被观察的目标对象 继承Observable
 */
public class Blog extends Observable{
    private String authorName;
    private String blogContent;

    public String getAuthorName() {
        return authorName;
    }

    public void setAuthorName(String authorName) {
        this.authorName = authorName;
    }

    public Blog(String authorName) {
        this.authorName = authorName;
    }

    public String getBlogContent() {
        return blogContent;
    }

    public void setBlogContent(String blogContent) {
        this.blogContent = blogContent;
        //博客内容已经有了,说明博客更新了,提醒观察者
        this.setChanged();
        //主动通知
        this.notifyObservers(blogContent);
        this.notifyObservers();
    }
}

客户端类
public class Main {

    public static void main(String[] args) {
        Blog blog = new Blog("张三");
        blog.setBlogContent("博客更新啦");
        BlogReader blogReader1 = new BlogReader();
        blogReader1.setBlogReaderName("阅读者1");
        BlogReader blogReader2 = new BlogReader();
        blogReader2.setBlogReaderName("阅读者2");
        BlogReader blogReader3 = new BlogReader();
        blogReader3.setBlogReaderName("阅读者3");
        blogReader1.update(blog,"更新");
        blogReader2.update(blog);
        blogReader3.update(blog);
    }
}
运行结果
阅读者1收到了博客更新消息,获得内容更新
阅读者2主动查看作者张三的更新内容博客更新啦
阅读者3主动查看作者张三的更新内容博客更新啦

Process finished with exit code 0

观察者模式的使用场景:1.当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化。2.如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要被连带改变。3.当一个对象必须通知其他的对象,例如手机电量不足,又希望这个对象和其他被通知的对象之间是松散耦合的。

区别对待观察者场景问题:
需求1,博客包含很多系列,读者1只关心android系列,读者2只关心java系列,读者3两个系列都关心。
需求2,博客更新android系列,读者1和读者3收到消息,做出不同反应。博客更新java系列,读者2和读者3收到消息,做出不同反应。
需求3,博客更新情感系列,不发送消息。

package com.company;

import java.util.ArrayList;
import java.util.Observable;

/**
 * Created by dell on 2018/4/17.
 */
public abstract class BlogWithTag extends Observable{
    public ArrayList<BlogReader> blogReaders = new ArrayList<>();
    public void attach(BlogReader blogReader){
        blogReaders.add(blogReader);
    }
    public void detach(BlogReader blogReader){
        blogReaders.remove(blogReader);
    }
    public abstract void notifyReaders();
}

package com.company;

import java.util.Observable;
/**
 * Created by dell on 2018/4/17.
 * 博客类 可以向订阅者发布更新
 */
public class Blog extends BlogWithTag {
    //作者姓名
    private String authorName;
    private ArticleInfo articleInfo;

    public ArticleInfo getArticleInfo() {
        return articleInfo;
    }

    public void setArticleInfo(ArticleInfo articleInfo) {
        this.articleInfo = articleInfo;
        this.notifyReaders();
    }

    public String getAuthorName() {
        return authorName;
    }

    public Blog(String authorName) {
        this.authorName = authorName;
    }

    @Override
    public void notifyReaders() {
        for (BlogReader blogReader : blogReaders) {
            if (this.articleInfo.getTag().equals("java")) {
                if (blogReader.getBlogReaderName().equals("reader1") || blogReader.getBlogReaderName().equals("reader3")) {
                    blogReader.update(this,"java");
                }
            }
            if (this.articleInfo.getTag().equals("android")) {

                if (blogReader.getBlogReaderName().equals("reader2") || blogReader.getBlogReaderName().equals("reader3")) {
                    blogReader.update(this);
                }
            }
        }
    }
}
package com.company;

import java.util.Observable;
import java.util.Observer;

/**
 *
 * Created by dell on 2018/4/17.
 * 重写update方法
 */
public class BlogReader implements Observer {
    private String blogReaderName;
    private String blogTag;
    private String remindBlog;
    public String getBlogReaderName() {
        return blogReaderName;
    }

    public BlogReader(String blogReaderName) {
        this.blogReaderName = blogReaderName;
    }
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(getBlogReaderName()+"收到了博客更新消息,获得内容"+arg);

    }
    public void update(Observable o) {
        Blog blog = (Blog)o;
        this.blogTag = ((Blog) o).getArticleInfo().getTag();
        if (blogTag == "java"){
            System.out.println(((Blog) o).getArticleInfo().getContent()+((Blog) o).getArticleInfo().getTag());
            System.out.println("java系列博客更新,去学习");
        }
        if (blogTag == "android"){
            System.out.println(((Blog) o).getArticleInfo().getContent()+((Blog) o).getArticleInfo().getTag());
            System.out.println("android系列博客更新,去实践");
        }
    }
}
package com.company;
/**
 *  需求1,博客包含很多系列,读者1只关心android系列,读者2只关心java系列,读者3两个系列都关心。
    需求2,博客更新android系列,读者1和读者3收到消息,做出不同反应。博客更新java系列,读者2和读者3收到消息,做出不同反应。
    需求3,博客更新情感系列,不发送消息。

    实现步骤:定义目标的抽象类和观察者的接口
    实现目标的类和观察者接口
 * */
public class Main {

    public static void main(String[] args) {
        Blog blog = new Blog("Cindy");

        BlogReader blogReader1 = new BlogReader("reader1");
        BlogReader blogReader2 = new BlogReader("reader2");
        BlogReader blogReader3 = new BlogReader("reader3");
        ArticleInfo articleInfo1 = new ArticleInfo("java 很好用","java");
        ArticleInfo articleInfo2 = new ArticleInfo("你会用activity么","android");
        ArticleInfo articleInfo3 = new ArticleInfo("broadcastReceiver 详解","android");
        blog.setArticleInfo(articleInfo1);
        blogReader1.update(blog);
        blog.setArticleInfo(articleInfo2);
        blogReader2.update(blog);
        blog.setArticleInfo(articleInfo3);
        blogReader3.update(blog);
    }
}
运行结果
java 很好用java
java系列博客更新,去学习
你会用activity么android
android系列博客更新,去实践
broadcastReceiver 详解android
android系列博客更新,去实践

.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java设计模式是一组经过实践验证的面向对象设计原则和模式,可以帮助开发人员解决常见的软件设计问题。下面是常见的23种设计模式: 1. 创建型模式(Creational Patterns): - 工厂方法模式(Factory Method Pattern) - 抽象工厂模式(Abstract Factory Pattern) - 单例模式(Singleton Pattern) - 原型模式(Prototype Pattern) - 建造者模式(Builder Pattern) 2. 结构型模式(Structural Patterns): - 适配器模式(Adapter Pattern) - 桥接模式(Bridge Pattern) - 组合模式(Composite Pattern) - 装饰器模式(Decorator Pattern) - 外观模式(Facade Pattern) - 享元模式(Flyweight Pattern) - 代理模式(Proxy Pattern) 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility Pattern) - 命令模式(Command Pattern) - 解释器模式(Interpreter Pattern) - 迭代器模式(Iterator Pattern) - 中介者模式(Mediator Pattern) - 备忘录模式(Memento Pattern) - 观察者模式(Observer Pattern) - 状态模式(State Pattern) - 策略模式(Strategy Pattern) - 模板方法模式(Template Method Pattern) - 访问者模式(Visitor Pattern) 4. 并发型模式(Concurrency Patterns): - 保护性暂停模式(Guarded Suspension Pattern) - 生产者-消费者模式(Producer-Consumer Pattern) - 读写锁模式(Read-Write Lock Pattern) - 信号量模式(Semaphore Pattern) - 线程池模式(Thread Pool Pattern) 这些设计模式可以根据问题的特点和需求来选择使用,它们提供了一些可复用的解决方案,有助于开发高质量、可维护且易于扩展的软件系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值