java设计模式 GOF23 04 原型模式

一.原型模式介绍

因为java中new一个新对象比clone一个对象需要花费等多的资源,所以一般需要

在短时间内创建大量对象并且new对象的过程需要耗费比较多的资源使用原型模式。

想要clone一个类需要这个类实现Cloneable接口,重载clone方法,这个接口在底层

通过内存拷贝实现clone对象,因此效率很高。

package com.lz.prototype;

import java.util.Date;

public class ShallowClone implements Cloneable{
    private String name;
    private int age;
    private Date date;
    public ShallowClone() {
    }

    public ShallowClone(String name, int age, Date date) {
        super();
        this.name = name;
        this.age = age;
        this.date = date;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        return obj;
    }
}
package com.lz.prototype;

import java.util.Date;

public class ShallowTest {
    public static void main(String[] args) {
        ShallowClone sc1 = new ShallowClone("laro", 20, new Date());
        System.out.println(sc1);
        System.out.println(sc1.getName());
        System.out.println(sc1.getAge());
        System.out.println(sc1.getDate());
        ShallowClone sc2 = null;
        try {
            sc2 = (ShallowClone) sc1.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        sc1.setDate(new Date());
        System.out.println(sc2);
        System.out.println(sc2.getName());
        System.out.println(sc2.getAge());
        System.out.println(sc2.getDate());
    }
}

二.原型模式效率检测

下面是一个简单的效率测试

package com.lz.prototype;

public class Efficiency {
    public static void main(String[] args) throws CloneNotSupportedException {
        test01();
        T s = new T();
        test02(s);
    }

    public static void test01() {
        long start = System.currentTimeMillis();
        for ( int i=0; i<1000; i++ ) {
            T s = new T();
        }
        long end = System.currentTimeMillis();
        System.out.println((end-start)+"毫秒");
    }

    public static void test02(T s) throws CloneNotSupportedException {
        long start = System.currentTimeMillis();
        for ( int i=0; i<1000; i++ ) {
            T copy = (T) s.clone();
        }
        long end = System.currentTimeMillis();
        System.out.println((end-start)+"毫秒");
    }
}

class T implements Cloneable{
    public T() {
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

三.浅拷贝与深拷贝

下面是一个简单代码实现当然上面的代码只实现了浅拷贝,浅拷贝的含义是只clone这个对象本身,而这个类里面包含的其他引用对象并没有

实现clone。这里想要实现深拷贝需要改动代码

package com.lz.prototype;

import java.util.Date;

public class DeepClone implements Cloneable{
    private String name;
    private int age;
    private Date date;
    public DeepClone() {
    }

    public DeepClone(String name, int age, Date date) {
        super();
        this.name = name;
        this.age = age;
        this.date = date;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    /*
     * 实现深拷贝
     * @see java.lang.Object#clone()
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object obj = super.clone();
        DeepClone dc = (DeepClone) obj;
        dc.date = (Date) this.date.clone();
        return obj;
    }
}

简单的实现深clone很简单,只需要将需要clone的类的内部的引用类也clone即可。

但是这种方法在比较复杂的类中就不容易实现了,这里还可以使用序列化和反序列化实现clone

当然一个类想实现序列化和反序列话需要实现Serializable接口

下面是一个简单的代码实现:

package com.lz.prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;

/*
 * 序列化反序列化clone对象
 */
public class Test01 {
    public static void main(String[] args) throws Exception {
        Sheep s1 = new Sheep("tom", new Date(1000000000L));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(s1);
        byte[] bytes = bos.toByteArray();
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bis);
        Sheep s2 = (Sheep) ois.readObject();
        System.out.println("测试前");
        System.out.println(s1);
        System.out.println(s1.getName()+" " + s1.getBirthday());
        System.out.println(s2);
        System.out.println(s2.getName()+" " + s2.getBirthday());

        s1.setName("laro");
        s1.setBirthday(new Date(1000000000L));

        System.out.println("测试后");
        System.out.println(s1);
        System.out.println(s1.getName()+" " + s1.getBirthday());
        System.out.println(s2);
        System.out.println(s2.getName()+" " + s2.getBirthday());
    }
}

class Sheep implements Cloneable, Serializable{
    private String name;
    private Date birthday;
    public Sheep() {
    }
    public Sheep(String name, Date birthday) {
        super();
        this.name = name;
        this.birthday = birthday;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
时间: 2024-08-02 11:03:29

java设计模式 GOF23 04 原型模式的相关文章

《Java设计模式》之原型模式

原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象.这就是原型模式的用意. 原型模式的结构 原型模式要求对象实现一个可以"克隆"自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例.这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建. 原型模式有两种表现形式:(1)简单形式.(2)登记形式,这两

java设计模式 GOF23 09 组合模式

一.组合模式简介 把整体和部分的关系用树形结构表示,从而可以统一处理. 二.组合模式实现细节 1)抽象构建:定义叶子和容器的共同特点. 2)叶子:没有子节点 3)容器:有容器的特征,可以包含子节点(一般实现的时候在这里添加容器存放子节点) 三.简单代码实现 package com.lz.combination; import java.util.ArrayList; import java.util.List; /* * 抽象构建 */ public interface IComponent {

java设计模式 GOF23 10 外观模式

一.外观模式简介 外观模式是为了解决类与类之间的依赖关系,这种模式将类与类之间的关系放到一个Facade类中,从而降低类与类之间的耦合. 二.简单代码实现 package com.lz.facade; /* * 外观模式 * 门面对象 */ public class RegisterFacade { public void register() { new 南京工商局().checkName(); new 南京税务局().taxCertificata(); } } package com.lz.

java设计模式 GOF23 02 工厂模式

package com.lz.factory.simpleFactory; /* * * 补充:面向对象基本原则 * OCP:(开闭原则)添加新功能不应该修改原有代码,而是添加新的类 * DIP:(依赖倒转原则)依赖接口编程 * LOD:(迪米特法则)降低耦合,只和必要的对象通信 * 静态工厂类 { * 创建者和调用者的分离 * * 简单工厂问题:添加新功能需要修改代码 * } * 工厂方法类{ * 代码过多 * } * 两者比较 * 简单工厂结构代码更简单 * 工厂方法更难维护 * 总结:工厂

Java描述设计模式(05):原型模式

一.原型模式简介 1.基础概念 原型模式属于对象的创建模式.通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象. 2.模式结构 原型模式要求对象实现一个可以"克隆"自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例.这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建. 3.代码实现 1).UML关系图 Java描述设计模

设计模式学习05—原型模式

一.动机与定义 之前学习原型模式一直以为原型模式目的是为了方便的创建相同或相似对象,用复制对象的方式替换new的方式,还研究了深克隆和浅克隆.最近仔细看了GOF的设计模式,发现原型模式的本意并不仅仅是复制对象这么简单. 复制对象确实是一方面,当我们需要大量相似,甚至相同对象的时候,除了一个个的new之外,还可以根据一个原型,直接复制出更多的对象.但是如果把原型模式认为只是复制对象这么简单就错了. 创建型模式主要讲如何创建对象,通常包含何时创建,谁来创建,怎么创建等.GOF书里面写的意图是,用原型

设计模式学习04—建造者模式

一.动机与定义 创建对象时,我们知道可以使用工厂方式来创建,使调用者和具体实现解耦,但是有一种情况,当要创建的多个对象之间重复性较大,只有创建步骤.组装顺序或者内部构件不同时,工厂模式就需要进一步的演化了,如我们去KFC,有很多种套餐,比如套餐1(薯条+可乐+汉堡),套餐2(鸡肉卷+薯条+可乐),这个套餐就是我们要获取的复杂对象,那么程序如何创建出这种对象呢. 我们看到套餐的内容很多是一样的,那么我们是不是可以考虑将创建单个食品(如鸡肉卷.可乐等)方法提取出来,使用单独一个类协调这些食品的组合比

一起学java设计模式--适配器模式(结构型模式)

适配器模式 现有一个接口DataOperation定义了排序方法sort(int[]) 和查找方法search(int[], int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法,类BinarySearch 的binarySearch(int[], int)方法实现了二分查找算法.现使用适配器模式设计一个系统,在不修改源代码的情况下将类QuickSort和类BinarySearch的方法适配到DataOperation接口中.绘制类图并编程实现. (要求实现

Java设计模式之接口型模式总结

摘要: 原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6508967.html 之前认真学习了Java设计模式中的四大接口型模式,分别为:适配器模式(Adapter).外观模式(Facade).合成模式(Composite).桥接模式(Bridge). 1.在此处再温习一下四种设计模式: (1)适配器模式: 我们能够访问的类中不存在我们要访问的内容时,就可以使用这个适配器模式,当然就类而言,其实不存在什么不能被访问,这里的不能访问都是人