美文网首页
Java 原型模式

Java 原型模式

作者: CodeDuan | 来源:发表于2022-01-27 17:23 被阅读0次

    一、简介

    用一个已经创建的实例作为原型,通过复制改原型对象来创建一个和原型对象相同的新对象。

    原型模式是创建型模式的一种,主要用于创建重复的对象,

    主要角色:

    抽象原型类:规定具体原型对象必须实现的clone()方法。

    具体原型类:实现抽象原型的clone()方法。

    访问类:使用具体原型类的clone()方法复制出新的对象。

    二、实现

    原型模式可以分为浅克隆和深克隆:

    浅克隆:创建一个新对象,新对象的属性和原对象完全相同,但是非基本数据类型,仍指向原有属性对象的内存地址。

    深克隆:创建一个新对象,属性中的对象也会被克隆,不指向原对象的内存地址。

    三、浅克隆

    举例:

    比如我有一个老婆,这个老婆身材完美,前凸后翘,但是一个老婆满足不了我,我想多要一个一模一样的老婆,此时可以通过原型模式复制出新的老婆。

    代码实现:

    抽象原型类:

    java的Object类中提供了clone()方法来实现克隆,Cloneable接口是指上面说到的抽象原型类,所以我们使用Cloneable当作抽象原型类。

    具体原型类:

    //老婆类 实现Cloneable接口
    public class Wife implements Cloneable {
        private int age = 20;
        private int height = 165;
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int getHeight() {
            return height;
        }
    
        public void setHeight(int height) {
            this.height = height;
        }
    
        //重写clone方法
        @Override
        public Wife clone() throws CloneNotSupportedException {
            return (Wife)super.clone();
        }
    
        @Override
        public String toString() {
            return "Wife{" +
                    "age=" + age +
                    ", height=" + height +
                    '}';
        }
    }
    

    使用:

    public static void main(String[] args) throws CloneNotSupportedException {
            //创建原型对象
            Wife wife = new Wife();
            //通过原型对象创建新对象
            Wife wife2 = wife.clone();
            //要一个大一些的
            wife2.setHeight(170);
        }
    

    输出:

    Wife{age=20, height=165}
    Wife{age=20, height=170}
    

    此时通过原型模式(浅拷贝)就创建出了我的第二个身高不同老婆。非常满意。

    四:深克隆

    举例:

    为了验证深浅克隆的区别,我们把Wife中的参数封装成对象试试看。

    //老婆属性
    public class Param implements Serializable{
        private int age = 20;
        private int height = 165;
    
        public Param(int age,int height){
            this.age = age;
            this.height = 165;
        }
        
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int getHeight() {
            return height;
        }
    
        public void setHeight(int height) {
            this.height = height;
        }
    
        @Override
        public String toString() {
            return "Param{" +
                    "age=" + age +
                    ", height=" + height +
                    '}';
        }
    }
    
    //老婆类
    public class Wife implements Cloneable,Serializable {
        //老婆属性
        private Param param;
    
        public Param getParam() {
            return param;
        }
    
        public void setParam(Param param) {
            this.param = param;
        }
    
        @Override
        public Wife clone() throws CloneNotSupportedException {
            return (Wife)super.clone();
        }
    }
    

    使用:

    public static void main(String[] args) throws CloneNotSupportedException {
            //创建原型对象
            Wife wife = new Wife();
            //设置属性
            wife.setParam(new Param(20,165));
    
            //通过原型对象创建新对象
            Wife wife2 = wife.clone();
            //修改新对象的身高
            wife2.getParam().setHeight(170);
            System.out.println(wife.getParam().toString());
            System.out.println(wife2.getParam().toString());
        }
    

    输出:

    Param{age=20, height=170}
    Param{age=20, height=170}
    

    为什么只修改了wife2的身高,wife的身高也变了呢?这怎么行,原因就是因为目前还是浅克隆,写这段代码就是为了验证深浅克隆,可以看出 wife中的params只要修改了一个,就都会发生变化,可见两个param所指向的内存地址还是相同的。解决办法就是深克隆。


    深克隆实现:

    深克隆可以使用流的方式来实现,只需要在原型类中的clone方法中来实现即可。

    @Override
        public Wife clone() throws CloneNotSupportedException {
            //获取clone的对象
            Wife wife = (Wife) super.clone();
            try{
                //把对象写入到字节流中
                ByteArrayOutputStream baos =new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(wife);
    
                //把字节流转化为对象
                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bais);
                return (Wife) ois.readObject();
            }catch (IOException | ClassNotFoundException e){
                e.printStackTrace();
            }
            return wife;
        }
    

    使用输出:

    Param{age=20, height=165}
    Param{age=20, height=170}
    

    此时通过原型模式的深克隆就得到了两个身高不一样的老婆。

    相关文章

      网友评论

          本文标题:Java 原型模式

          本文链接:https://www.haomeiwen.com/subject/fxpahrtx.html