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 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-20(01)总结,递归,IO流

1:递归(理解) (1)方法定义中调用方法本身的现象 举例:老和尚给小和尚讲故事,我们学编程 (2)递归的注意事项; A:要有出口,否则就是死递归 B...

3289
来自专栏微信公众号:Java团长

Java中的十个"单行代码编程"(One Liner)

本文列举了十个使用一行代码即可独立完成(不依赖其他代码)的业务逻辑,主要依赖的是Java8中的Lambda和Stream等新特性以及try-with-resou...

832
来自专栏Jackson0714

02.你真的知道线程安全的“单件模式”吗?

2647
来自专栏微信公众号:Java团长

Java基础知识详细总结

ClassLoader使用的是双亲委托模型来搜索类的,每个ClassLoader实例都有一个父类加载器的引用(不是继承的关系,是一个包含的关系),虚拟机内置的类...

883
来自专栏java达人

ConcurrentHashMap使用示例

作者:mononite 链接:https://my.oschina.net/mononite/blog/144329(点击文末阅读原文前往) Concurren...

2088
来自专栏Java学习网

10个常见的 Java 错误及避免方法之第二集(后续持续发布)

当程序缺少关闭大括号(“}”)时,Java代码中就会发生此错误消息。 有时我们可以通过在代码的末尾放置大括号来快速修复错误。

663
来自专栏Java Edge

深入理解并发容器-ConcurrentHashMap(JDK8版本)1 概述3应用场景4 源码解析

2678
来自专栏码匠的流水账

bloomfilter的简单实现

布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的,可以用于检索一个元素是否在一个集合中。

381
来自专栏拭心的安卓进阶之路

并发编程6:CopyOnWriteArrayList 的写时复制

首先提个问题: 线程安全的 List 集合有什么? CopyOnWriteArrayList 的特点以及使用场景? 如果这个问题你答不上来,那这篇文章可能就...

2218
来自专栏菩提树下的杨过

common-pool2 学习:thrift连接池的另一种实现

对象池是一种很实用的技术,经典的例子就是数据库连接池。去年曾经从零开始写过一个thrift客户端连接池。如果不想重造轮子,可以直接在apache开源项目comm...

2258

扫码关注云+社区