喵星之旅-沉睡的猫咪-原型模式

一、原型模式是什么?

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。专业称呼为“CV大法”。

对于java中,复制对象的困难在我们很可能复制了当前对象,但是对象内的引用却只是拿来了,内部深层的对象没有重新创建,所以复制出的对象和原对象存在共用的部分,相互影响。也就是所谓的浅克隆和深克隆。本文只考虑深克隆。这种克隆的功能可以使单独的工具类,也可以是对象自身功能,这里只演示对象自身功能。

二、java代码实现原型模式

原型类(需要实现序列化接口

 

package create.prototype;

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

import com.alibaba.fastjson.JSON;
/**
 * 
 * @author bunny~~我是兔子我会喵,我叫喵星兔。
 * 原型模式
 */
public class MyPrototype implements Serializable {
    

    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private List<String> title;
    /**
     * 通过序列化实现深度克隆
     * @return
     */
    public MyPrototype copyByIO() {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (MyPrototype)ois.readObject();
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 通过json实现深度克隆
     * @return
     */
    public MyPrototype copyByJson() {
        try {
            String jsonString = JSON.toJSONString(this);
            return (MyPrototype) JSON.parseObject(jsonString, this.getClass());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    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 List<String> getTitle() {
        return title;
    }
    public void setTitle(List<String> title) {
        this.title = title;
    }
    @Override
    public String toString() {
        return "MyPrototype [name=" + name + ", age=" + age + ", title=" + title + "]";
    }

}

 

测试类

package create.prototype;

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

public class Test {

    public static void main(String[] args) {
        MyPrototype p0 = new MyPrototype();
        p0.setAge(11);
        p0.setName("kitty");
        List<String> title = new ArrayList<>();
        p0.setTitle(title );
        System.out.println(p0);
        MyPrototype p1 = p0.copyByIO();
        p1.getTitle().add("p1");
        System.out.println(p0);
        System.out.println(p1);
        System.out.println(p0 == p1);
        System.out.println(p0.getTitle() == p1.getTitle());
        MyPrototype p2 = p0.copyByJson();
        p2.getTitle().add("p2");
        System.out.println(p0);
        System.out.println(p2);
        System.out.println(p0 == p2);
        System.out.println(p0.getTitle() == p2.getTitle());
    }

}

 

三、总结

原型模式在编码过程中,绝对是所有设计模式出场频率最高的一种。正所谓“我们不是代码的生产者,我们只是代码的搬运工”。平时我们如果有一个需求,比如上传文件。这时我们不会找到相应的工具,然后去阅读操作手册(就是new对象的过程),而是找寻一个上传样例,用一种叫“CV”的技术实现在我们的代码中(原型模式),进而根据具体的环境进行调试,最终实现功能。

经典之中亦是不少原型的出现,比如“三人行必有我师”、“前事不忘后事之师”。但是是否选择原型还需进一步考虑。因为原型也不是万能的,原型的成功案例很多,但是失败的也是不少。如果各方面允许,其实不使用原型必然是安全的,当然可能不高效。当我们对对象目标了解程度足够高时,选择原型必然是事半功倍。任何的设计模式只要我们足够的掌控,都是我们手中的利器。在掌控不足的情况下也必然是手中的噩梦。

 

posted @ 2020-03-01 13:05  喵星兔  阅读(189)  评论(0编辑  收藏  举报