Java设计模式之原型模式

原型模式属于对象的创建模式。通过给出一个原型对象来指明所创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。相比于new出来的对象,原型模式效率高,因为原型直接复制的是对象的二进制,不是先new 对象再赋值。
原型模式的复制分为浅复制和深复制。浅复制中,对象的基本数据类型及其封装类会被复制,而引用类型,如对象、数组和集合类等不被复制;深复制就是复制所有数据,当然包括引用类型。
以下先演示浅复制。
为了以后的扩展,定义了一个继承了Cloneable的Prototype的接口。要想实现复制对象,必须实现Cloneable接口,并在实现类调用clone方法。

package come.example.prototype;

interface Prototype extends Cloneable{
    public Prototype clonePrototype();

}

定义了一个Pen的类

package come.example.prototype;

public class Pen{
    private String color;

    public String getColor() {
        return color;

    }

    public void setColor(String color) {
        this.color = color;

    }}

定义一个Student类,有基本数据类型和引用类型的成员变量

package come.example.prototype;

import java.awt.List;
import java.util.ArrayList;

public class Student implements Prototype{
    private String name;
    private int age;
    private Pen pen;
    private ArrayList<String> datas;

    public ArrayList<String> getDatas() {
        return datas;
    }
    public void setDatas(ArrayList<String> datas) {
        this.datas = datas;
    }
    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 Pen getPen() {
        return pen;
    }
    public void setPen(Pen pen) {
        this.pen = pen;
    }

    public Prototype clonePrototype(){
        Student student = null;
        try {
            student = (Student) super.clone();

        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student;
    }

}

定义了Client测试类,为Student 对象属性赋值,并调用clonePrototype()方法克隆另一个Student 的对象

package come.example.prototype;

import java.util.ArrayList;

public class Client {
    public static void main(String[] args) {
        Student st1 = new Student();
        st1.setAge(18);
        st1.setName("晓明");
        Pen pen = new Pen();
        pen.setColor("红色");
        st1.setPen(pen);
        ArrayList<String> datas = new ArrayList<String>();
        datas.add("aa");
        st1.setDatas(datas);


        Student st2 = (Student) st1.clonePrototype();
        st2.setName("小李");
        st2.getPen().setColor("黄色");
        ArrayList<String> d = st2.getDatas();
        d.clear();

        System.out.println("st1的姓名: " + st1.getName() + " 笔颜色: "+ st1.getPen().getColor() + " 数据: " + st1.getDatas().size());
        System.out.println("st2的姓名: " + st2.getName() + " 笔颜色: "+ st2.getPen().getColor()+ " 数据: " + st2.getDatas().size());

    }

}


打印结果是:

st1的姓名: 晓明  st1的年龄: 18 笔颜色: 黄色 数据: 0
st2的姓名: 小李  st2的年龄: 15 笔颜色: 黄色 数据: 0

从结果可以看出来,st2修改数据后,st1的姓名和年龄没有发生改变,但是笔的颜色和Arraylist的长度发生了改变,说明st1和st2的引用类型的属性指向相同的对象。这是浅复制存在的问题,而深复制能解决这个问题。
修改下代码。
Pen类也要调用clone方法进行复制

package come.example.prototype;

public class Pen implements Prototype{
    private String color;

    public String getColor() {
        return color;

    }

    public void setColor(String color) {
        this.color = color;

    }

    @Override
    public Prototype clonePrototype() {
        Prototype pen = null;
        try {
            pen = (Prototype) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

        return pen;
    }



}

Student类中的clonePrototype方法修改为

public Prototype clonePrototype(){
        Student student = null;
        try {
            student = (Student) super.clone();
            Pen pen = (Pen) this.pen.clonePrototype();
            ArrayList<String> daList = null;
            if (datas != null) {
                daList = (ArrayList<String>) datas.clone();         
                }
            student.setDatas(daList);
            student.setPen(pen);
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return student;
    }

`打印结果为


st1的姓名: 晓明  st1的年龄: 18 笔颜色: 红色 数据: 1
st2的姓名: 小李  st2的年龄: 15 笔颜色: 黄色 数据: 0

深复制的目的是,复制出来的对象和被复制的对象及其引用类型的属性都指向不同的内存地址。

下载demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值