责任链模式和观察者模式

责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

这种模式中,通常每个接收者都包含对另一个接收者的调用。如果一个对象不能处理请求,那么它会把相同的请求传给下一个接收者,以此类推。

介绍

意图:避免请求发送者和接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理他为止。

主要解决:职责链上处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链中请求的发送者和处理者解耦了。

何时使用:在处理消息的时候以过滤很多道。

如何解决:拦截的类都实现统一接口。

应用实例: 1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。

优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。

缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。

使用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。

注意事项:在 JAVA WEB 中遇到很多应用。

观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。

介绍

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。

何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。

如何解决:使用面向对象技术,可以将这种依赖关系弱化。

关键代码:在抽象类里有一个 ArrayList 存放观察者们。

应用实例: 1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。 2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作。

优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。

缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

使用场景:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。

注意事项: 1、JAVA 中已经有了对观察者模式的支持类。 2、避免循环引用。 3、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式。

 

结合案例:

1.Observed 被观察者(员工):产生一个请求

2.Leader 领导(模拟观察者):员工产生请求,领导查到进行操作。

3.Leader 每个领导内部定义另一接收者,形成接收者的对象链。处理请求。

1.定义Leader抽象类:包含对象名称,责任链后期对象,观察方法,处理请求。

/**
 * 抽象类
 * Created by Sue on 2018/8/24
 */
public abstract class Leader {
    protected String name;
    protected Leader nextLeader;//责任链后期对象
    public abstract void update(ProjectRequest projectRequest);

    public Leader() {
    }

    public Leader(String name) {
        this.name = name;
    }
    public void setNextLeader(Leader nextLeader){
        this.nextLeader = nextLeader;
    }
    //请求处理核心业务方法//public abstract void VerifyRequest(ProjectRequest projectRequest);
    public void VerifyRequest(ProjectRequest projectRequest){
        System.out.println(name + "收到请求:" + projectRequest);
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入意见:");
        String advice = scanner.next();
        if (advice.equalsIgnoreCase("y")) {
            projectRequest.setRatify(true);
            System.out.print(name + "已同意");
            if (nextLeader!=null){
                System.out.println(",请求提交给" + this.nextLeader.name + "!");
                System.out.println();
                this.nextLeader.VerifyRequest(projectRequest);
            }
        }else {
            projectRequest.setRatify(false);
            System.out.println("请求被" + name + "拒绝!");
        }
    }
}

2.定义被观察者Observed类:产生请求,添加订阅,通知观察者

/**
 * Created by Sue on 2018/8/30
 */
public class Observed {
    private String name;
    private List<Leader> leaders = new ArrayList<>();//状态改变

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Leader> getLeaders() {
        return leaders;
    }

    public void setLeaders(List<Leader> leaders) {
        this.leaders = leaders;
    }

    public void setMsg(ProjectRequest projectRequest) {
        System.out.println(this.getName() + "产生请求:" + projectRequest);
        notifyAll(projectRequest);
    }
    //订阅
    public void addAttach(Leader leader) {
        leaders.add(leader);
    }
    //通知所有订阅的观察者
    private void notifyAll(ProjectRequest projectRequest) {
        for (Leader leader : leaders) {
            leader.update(projectRequest);
        }
    }
}

3.请求类ProjectRequest

public class ProjectRequest {
    private String no;
    private String name;
    private String describe;
    private boolean isRatify;
    //Getter and Setter  toString()方法  构造方法略 
}

4.创建实例LeaderA、LeaderB、LeaderC

/**
 * Created by Sue on 2018/8/24
 */
public class LeaderA extends Leader {

    @Override
    public void update(ProjectRequest projectRequest) {
        VerifyRequest(projectRequest);
    }

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

    @Override
    public void VerifyRequest(ProjectRequest projectRequest) {
        super.VerifyRequest(projectRequest);
    }
}


public class LeaderB extends Leader {
    public LeaderB(String name){
        super(name);
    }
    @Override
    public void update(ProjectRequest projectRequest) {
        VerifyRequest(projectRequest);
    }
    @Override
    public void VerifyRequest(ProjectRequest projectRequest) {
        super.VerifyRequest(projectRequest);
    }
}


public class LeaderC extends Leader {
    public LeaderC(String name){
        super(name);
    }
    @Override
    public void update(ProjectRequest projectRequest) {
        VerifyRequest(projectRequest);
    }
    @Override
    public void VerifyRequest(ProjectRequest projectRequest) {
        super.VerifyRequest(projectRequest);
    }
}

5.测试类ChainTest

/**
 * Created by Sue on 2018/8/24
 */
public class ChainTest {

    public static void main(String[] args) {
        Leader a = new LeaderA("主任");
        Leader b = new LeaderB("经理");
        Leader c = new LeaderC("总经理");
        //责任链对象关系
        a.setNextLeader(b);
        b.setNextLeader(c);
        //创建被观察者
        Observed observed = new Observed();
        //加入观察者
        observed.addAttach(a);

        //被观察者产生请求
        ProjectRequest request = new ProjectRequest("00001","项目A","描述");
        observed.setName("被观察者A");
        observed.setMsg(request);
    }
}

测试结果

 

posted @ 2018-08-30 23:37  少说点话  阅读(1711)  评论(0编辑  收藏  举报
网站运行: