从观察者模式谈设计模式

 观察者模式,又称发布-订阅(Publish/Subscribe)模式,当对象间存在一对多关系,并且一个对象的状态被其他多个对象关注(该对象状态的改变对其他对象有影响)时,可以使用该模式。特点是:一个对象(目标对象)的状态发生改变,进行广播通知所有的依赖对象(观察者对象)。以明星和粉丝为例(不一定十分恰当),明星就是主题发布者,粉丝们就是订阅者;明星的粉丝关注数(粉丝集合),就像是主题发布者持有订阅者(观察者)的集合;明星有了新动态发条微博广播,所有关注她的粉丝都会被通知,不同的粉丝对该消息进行不同的响应。我是一个张韶涵粉丝,下面上代码:

package com.xfkj.observerPatten;

/**
 * 主题发布接口
 */
public interface ISubject {
    void attach(IObserver iObserver);
    void dettach(IObserver iObserver);
    void notifyObservers();

}
package com.xfkj.observerPatten;

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


/**
 * 某个主题发布者
 */
public class Subject implements ISubject {
    private List<IObserver> observers=new ArrayList<>();
    private String state;

    public List<IObserver> getObservers() {
        return observers;
    }

    public void setObservers(List<IObserver> observers) {
        this.observers = observers;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @Override
    public void attach(IObserver iObserver) {
        observers.add(iObserver);
    }

    @Override
    public void dettach(IObserver iObserver) {
        observers.remove(iObserver);

    }

    @Override
    public void notifyObservers() {
        for (IObserver observer:observers) {
            observer.update();
        }
    }
}


package com.xfkj.observerPatten;

/**
 * 观察者接口
 */
public interface IObserver {
    void update();
}



package com.xfkj.observerPatten;

/**
 * 抽象观察者
 */
public class AbstractObserver {
    private String observerName;
    private String observerState;
    private Subject subject;

    public String getObserverName() {
        return observerName;
    }

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

    public String getObserverState() {
        return observerState;
    }

    public void setObserverState(String observerState) {
        this.observerState = observerState;
    }

    public Subject getSubject() {
        return subject;
    }

    public void setSubject(Subject subject) {
        this.subject = subject;
    }

}



package com.xfkj.observerPatten;

/**
 *观察者之一
 */

public class Observer extends AbstractObserver implements IObserver {
    public Observer(Subject subject,String observerName){
        this.setObserverName(observerName);
        this.setSubject(subject);
    }
    @Override
    public void update() {
        watchConcert();
    }
    private void watchConcert(){
        this.setObserverState(this.getSubject().getState());
        System.out.println(this.getObserverName()+"观察到"+this.getObserverState()+"->决定去看");
    }
}
package com.xfkj.observerPatten;

/**
 * 另外一个观察者
 */
public class AnotherObserver extends AbstractObserver implements IObserver {
    public AnotherObserver(Subject subject,String observerName){
        this.setObserverName(observerName);
        this.setSubject(subject);
    }
    @Override
    public void update() {
        notWatchConcert();
    }

    private void notWatchConcert() {
        this.setObserverState(this.getSubject().getState());
        System.out.println(this.getObserverName()+"观察到"+this.getObserverState()
                +"->跟我没关系决定不去看");
    }
}


package com.xfkj.observerPatten;
/*
程杰老师的《大话设计模式》里讲到观察者模式的缺点是各个实现类的方法签名未必都一致,所以在Subject里统一调用update()方法
时会呈现一定的弊端,书中采用C#中的事件委托机制,来化解这个问题。其实也不然,不必要如此费周折。23种设计模式抛开具体应用场景
,核心的问题是解耦。世上本无事;如果存在理想的需求不变模型,那根据奥卡姆剃刀原理,能用最少的类就用最少的类;而现实
是需求是不断变化的,为了应对这种变化,对于那种具有变化风险同时又承担着“牵一发而动全身”的类,就需要解耦和;所谓牵一发而
动全身,是因为它的业务频繁,被多个类依赖,但需求变化的粒度是粗细不定的,为了单方面满足某个需求而改动被多处依赖调用的类,
就会波及其他调用者,毕竟事物是普遍联系的。因此,为了应对可能性的变化,需要通过抽象类、接口来隔离变化,依赖抽象而不依赖具体。
矛盾是一把双刃剑,一面它带来问题,另一面就是问题的答案。耦合是因为两个类联系太紧密了,而解耦恰恰就是反其道而行之。由此诞生了一
个伟大的思想“计算机中任何问题,都可以添加一个中间层来解决”,遗憾的是,这句名言的出处无从考证。从这个意义上来说,23种设计模式
再往上抽象就是中间件思想,而且模式各自结构也有相似之处。这就像金庸的武侠小说里提倡的“无招胜有招”的境界,在功底扎实之后,23种设计模式
即使记不全,记住中间件这个无上心法也知道该怎么施展拳脚——随机应变。
如果说接口是类级别的中间件,那么本例中接口的各自实现类在复写的方法里调用私有方法,就是方法级的
中间件。所谓“其大无外,其小无内”,再细还能到变量级别,例如全局容器变量;再大还能大到模块、架构层面等。
 */
public class TestObserverPatten {
    public static void main(String[] args) {
        Subject subject=new Subject();
        IObserver observer=new Observer(subject,"真粉丝");
        IObserver observer2=new AnotherObserver(subject,"假粉丝");
        subject.attach(observer);
        subject.attach(observer2);
        subject.setState("张韶涵演唱会即将开始");
        subject.notifyObservers();

    }
}
运行结果:
真粉丝观察到张韶涵演唱会即将开始->决定去看
假粉丝观察到张韶涵演唱会即将开始->跟我没关系决定不去看
发布了24 篇原创文章 · 获赞 7 · 访问量 5327

猜你喜欢

转载自blog.csdn.net/GengMingHui_5/article/details/97189007