23种设计模式详解(五)

1.责任链模式(Chain of Responsibility)

有多个对象,每个对象持有对下一个对象的引用,这样就会形成一条链,请求在这条链上传递,直到某一对象决定处理该请求。但是发出者并不清楚到底最终那个对象会处理该请求,所以,责任链模式可以实现,在隐瞒客户端的情况下,对系统进行动态的调整。

Handler接口:

public interface Handler {
    public void operator();
}

Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象。

public abstract class abstractHandler {
    private Handler handler;

    public Handler getHandler() {
        return handler;
    }

    public void setHandler(Handler handler) {
        this.handler = handler;
    }
}

MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。

public class myHandler extends abstractHandler implements Handler {
    private String name;

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

    @Override
    public void operator() {
        System.out.println(name+"chain");
        if(getHandler()!=null){
            getHandler().operator();
        }

    }
}

测试:

public class Test {
    public static void main(String[] args){
        myHandler h1=new myHandler("h1");
        myHandler h2=new myHandler("h2");
        myHandler h3=new myHandler("h3");
        myHandler h4=new myHandler("h4");
        h3.setHandler(h4);
        h2.setHandler(h3);
        h1.setHandler(h2);
        h1.operator();
    }
}

结果:

责任链模式屏蔽了请求的处理过程,你发一个请求到底是谁处理的,这个你不用关心,只要你把请求抛给责任链的第一个处理者,最终返回一个处理结果(也可以不返回),作为请求者可以不用知道到底需要谁来处理,这是责任链模式的核心。

注意:链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。

2.访问者模式(Visitor Pattern)

简单来说,访问者模式就是一种分离对象数据结构与行为的方法,通过这种分离,可达到为一个被访问者动态添加新的操作而无需做其它的修改的效果。

Subject接口:

public interface Subject {
    //接受将要访问它的对象
    public void accept(Visitor visitor);
    //获取将要被访问的属性
    public String getSubject();
}

Visitor接口:

public interface Visitor {
    //存放要访问的对象
    public void visit(Subject subject);
}

Subject实现类:

public class mySubject implements Subject {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    @Override
    public String getSubject() {
        return "A";
    }
}

Vistor实现类:

public class myVisitor implements Visitor {
    @Override
    public void visit(Subject subject) {
        System.out.println("访问"+subject.getSubject());
    }
}

测试:

public class Test {
    public static void main(String[] args){
        Visitor visitor=new myVisitor();
        Subject su=new mySubject();
        su.accept(visitor);
    }
}

结果:

3.状态模式(State Pattern)

当对象的状态改变时,同时改变其行为,很好理解!状态模式就两点:1、可以通过改变状态来获得不同的行为。2、别人能同时看到你的变化。

举例:开门、关门。

状态类:

public class State {
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public void open(){
        System.out.println("开门");
    }
    public void close(){
        System.out.println("关门");
    }
}

状态类的替换类:

public class Change {
    private State state;

    public State getState() {
        return state;
    }

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

    public Change(State state) {

        this.state = state;
    }
    public void change(){
        if(state.getValue().equals("state1")){
            state.open();
        }else if(state.getValue().equals("state2")){
            state.close();
        }
    }
}

测试:

public class Test {
    public static void main(String[] args){
        State state=new State();
        Change change=new Change(state);
        //设置一种状态
        state.setValue("state1");
        //state.setValue("state2");
        change.change();

    }
}

结果:

状态模式相当于当某个对象在它的状态发生改变时,他的行为也随着发生较大变化。也就是说行为是受状态约束的情况下才可以使用,而且对象的状态最好控制在5个之内。

4.原型模式(Prototype Pattern)

原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。本小结会通过对象的复制,进行讲解。在Java中,复制对象是通过clone()实现的,先创建一个原型类:

public class Prototype implements Cloneable {
    @Override
    //super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的,具体怎么实现,了解JNI
    protected Object clone() throws CloneNotSupportedException {
        Prototype p= (Prototype) super.clone();
        return super.clone();
    }
}

举例深浅复制:

浅复制:对对象中的基本数据类型进行简单的赋值,如果存在动态成员和指针就会出现问题。

深复制:对对象中的动态成员重新开辟内存空间。

import java.io.Serializable;

class SerializableObject implements Serializable {
    private static final long serialVersionUID=1L;

}
import java.io.*;

public class Prototype implements Cloneable,Serializable{
    private static final long serialVersionUID = 1L;
    private String string;
    private SerializableObject obj;
    /* 浅复制 */
    public Object clone() throws CloneNotSupportedException{
        Prototype proto= (Prototype) super.clone();
        return proto;
    }
    /* 深复制 */
    public Object deepClone()throws IOException,ClassNotFoundException{
        /* 写入当前对象的二进制流 */
        ByteArrayOutputStream bos=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bos);
        oos.writeObject(this);
        /* 读出二进制流产生的新对象 */
        ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bis);
        return ois.readObject();

    }

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }

    public SerializableObject getObj(){
        return obj;
    }
    public void setObj(SerializableObject obj) {
        this.obj=obj;
    }
}

要实现深复制,需要采用流的形式读入当前对象的二进制输入,再写出二进制数据对应的对象。

源码:

链接: https://pan.baidu.com/s/1K-Cqy1WpD-tyemDJwKDRuA

密码: f3jh

原文发布于微信公众号 - Java大联盟(javaunion)

原文发表时间:2018-05-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏老码农专栏

在JavaScript中仿真Java的enum

11620
来自专栏企鹅号快讯

来仿一仿retrofit

为什么要重复造轮子 在开发领域有一句很流行的话就是不要重复造轮子,因为我们在开发中用到的很多东西早已有很多人去实现了,而且这些实现都是经过时间和开发者检验过的,...

19790
来自专栏一名叫大蕉的程序员

来人啊给我炸了那个Java虚拟机No.46

你指尖跃动的电光,是我此生不灭的信仰,唯我超电磁炮永世长存。 瞬间爆炸,完成单杀。 深度长文,非常非常长,执行这些程序可能导致机器完全死机,请遵照指示安全开车。...

23990
来自专栏智能算法

ZIP压缩算法详细分析及解压实例解释(下)

来源:esingchan - 博客园 链接:www.cnblogs.com/esingchan/p/3958962.html(点击尾部阅读原文前往) 7、ZIP...

72260
来自专栏nice_每一天

转载 Java设计模式

设计模式; 一个程序员对设计模式的理解: “不懂”为什么要把很简单的东西搞得那么复杂。后来随着软件开发经验的增加才开始明白我所看到的“复杂”恰恰就是设计模式的精...

13420
来自专栏不会写文章的程序员不是好厨师

浅析HystrixRollingNumber(用于qps计数的数据结构)

考虑到一种需求场景,我们需要统计系统qps、每秒平均错误率等。qps表示每秒的请求数目,能想到的最简单的方法就是统计一定时间内的请求总数然后除以总统计时间,所以...

32920
来自专栏青青天空树

java导出Excel文件

  最近在java上做了一个EXCEL的导出功能,写了一个通用类,在这里分享分享,该类支持多sheet,且无需手动进行复杂的类型转换,只需提供三个参数即可:

52810
来自专栏糊一笑

几个关于js数组方法reduce的经典片段

以下是个人在工作中收藏总结的一些关于javascript数组方法reduce的相关代码片段,后续遇到其他使用这个函数的场景,将会陆续添加,这里作为备忘。 jav...

47490
来自专栏云霄雨霁

Java--通配符类型

19640
来自专栏技术点滴

原型模式(Prototype)

原型模式(Prototype) 原型模式(Prototype) 意图:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。 应用:Java/C#中的...

19150

扫码关注云+社区

领取腾讯云代金券