设计模式之原型模式

原型模式:指定创建对象的种类,并且通过拷贝这些原型来创建新的对象,原型模式是一种创建型的设计模式,允许一个对象再创建另外一个可定制的对象,无需知道创建的细节。

工作原理:通过一个原型对象传给那个要创建的对象,这个要创建的对象通过请求原型对象拷贝他们自己来实施创建,即对象.clone()。

原理图形:

原理图结构说明:

Prototype:原型类,声明一个克隆自己的接口。

ConcretePrototype:具体的原型类,实现一个克隆自己的操作。

Client:让一个原型对象来克隆自己,从而创建一个新的对象且属性一致。

代码详解:通过学生和老师的对象信息来实现

/**
 * 学生的基本信息,要实现Cloneable,Serializable接口
 * @author Administrator
 *
 */
public class Student implements Cloneable,Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 4771131347919048627L;
    public String id;
    public String name;
    public Student(String id, String name) {
        this.id = id;
        this.name = name;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

/**
 * 老师的基本信息,老师包含学生的信息
 * @author Administrator
 *
 */
public class Teacher implements Cloneable,Serializable{

    private static final long serialVersionUID = -9053971804258100009L;
    
    public String name;
    public Student student;
    public Teacher(String name, Student student) {
        this.name = name;
        this.student = student;
    }
    public Teacher() {
    }
    
    /**
     * 深拷贝1
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Object deep = null;
        deep = super.clone();
        Teacher teacher = (Teacher)deep;
        teacher.student = (Student)student.clone();
        return teacher;
    }
    
    /**
     * 深拷贝2
     * @return
     */
    public Object deepClone() {
        //创建流对象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //当前这个对象以对象流的方式输出
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            Teacher t = (Teacher)ois.readObject();
            return t;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                System.out.println(e2.getMessage());
            }
        }
    }

}
 

测试代码:

public class TeacherDemo {

    public static void main(String[] args) throws Exception{
        Student student = new Student("10","李四");
        Teacher teacher = new Teacher("王老师",student);
        //浅拷贝的方法
//        Student s1 = (Student)student.clone();
//        Teacher t1 = (Teacher)teacher.clone();
//        Teacher t2 = (Teacher)teacher.clone();
//        System.out.println(t1.toString() + "student:" + t1.student.hashCode());
//        System.out.println(t2.toString() + "student:" + t2.student.hashCode());
        //深拷贝
        //深拷贝 - 方式2 通过对象的序列化实现 (推荐)
        Teacher t1 = (Teacher)teacher.deepClone();
        Teacher t2 = (Teacher)teacher.deepClone();
        System.out.println(t1.toString() + "student:" + t1.student.hashCode());
        System.out.println(t2.toString() + "student:" + t2.student.hashCode());
    }

深拷贝和浅拷贝:

对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性的值复制一份给新的对象。

对于数据类型是引用数据类型的成员变量,浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象,实际上两个成员变量都是指向同一个实例,在这种情况下在一个对象中修改该成员变量会影响另外一个对象的成员值,浅拷贝模式使用super.clone()来实现。

深拷贝介绍:

复制对象的所有基本数据类型的成员变量值,为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直接该对象可达的所有对象,也就是说,对象进行深拷贝要对整个对象进行拷贝。

深拷贝的实现方式1:重写clone方法来实现,2、通过对象的序列化实现深拷贝(推荐使用)。

原型模式注意细节:

1、创建新的对象比较复制时,可以利用原型模式简化对象的创建过程,同事也能提高效率。

2、不用重新初始化对象,而是动态的获取对象运行时的状态。

3、如果原始对象发送改变(增加或者减少属性),其他克隆对象也会发生相应的改变,无需修改代码。

4、在实现克隆的时候可能需要比较复制的代码。

5、原型模式的缺点是需要为每一个类配备一个克隆方法,这对全新的类来说不困难,但对已有的类进行改造的时候,需要修改源代码,违背了ocp原则。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值