原型模式详解

2020-06-16  本文已影响0人  奋斗的韭菜汪

不通过new(构造方法)创建对象,通过clone,或者copy的操作创建对象
使用场景:
1、类初始化消耗资源较多
2、new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
3、构造函数比较复杂
4、循环体中产生大量的对象时(比较常见)

浅克隆
jdk 的Cloneable是一个浅克隆
修改克隆对象后,原型对象也会发生变化(对于string这种应用类型clone只是copy了指针,并没有copy具体的值,修改是修改具体的值,所有原对象也会发生改变)

深克隆
1、序列化和反序列化
2、对象转json字符串,json字符串再转对象
深克隆的问题:性能不好,占用io
可以破坏单例(解决办法:不实现Cloneable接口,或者实现Cloneable接口重写clone方法,返回单例模式对外提供的唯一一个实例)
原型模式和单例模式是冲突的,不能同时存在一个对象中
1、简单实现:


public class BeanUtils {

    public static Object copy(Object prototype){
        Class clazz = prototype.getClass();
        Object instance = null;
        try {
            instance = clazz.newInstance();
            for(Field field : clazz.getDeclaredFields()){
                field.setAccessible(true);
                field.set(instance, field.get(prototype));
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return instance;
    }
}
public class ExamPaper {
    private String attribute1;
    private String attribute2;
    private String attribute3;
    private String attribute4;
    private String attribute5;
    private String attribute6;
    private String attribute11;
    private String attribute7;
    private String attribute8;
    private String attribute9;
    private String attribute10;

    public ExamPaper copy(){
        ExamPaper examPaper = new ExamPaper();
        examPaper.setAttribute1(this.attribute1);
        examPaper.setAttribute2(this.attribute2);
        examPaper.setAttribute3(this.attribute3);
        examPaper.setAttribute4(this.attribute4);
        examPaper.setAttribute5(this.attribute5);
        examPaper.setAttribute6(this.attribute6);
        examPaper.setAttribute7(this.attribute7);
        examPaper.setAttribute8(this.attribute8);
        examPaper.setAttribute9(this.attribute9);
        examPaper.setAttribute10(this.attribute10);
        examPaper.setAttribute11(this.attribute11);
        return examPaper;

    }
    public String getAttribute1() {
        return attribute1;
    }
    public void setAttribute1(String attribute1) {
        this.attribute1 = attribute1;
    }
    public String getAttribute2() {
        return attribute2;
    }
    public void setAttribute2(String attribute2) {
        this.attribute2 = attribute2;
    }
    public String getAttribute3() {
        return attribute3;
    }
    public void setAttribute3(String attribute3) {
        this.attribute3 = attribute3;
    }
    public String getAttribute4() {
        return attribute4;
    }
    public void setAttribute4(String attribute4) {
        this.attribute4 = attribute4;
    }
    public String getAttribute5() {
        return attribute5;
    }
    public void setAttribute5(String attribute5) {
        this.attribute5 = attribute5;
    }
    public String getAttribute6() {
        return attribute6;
    }
    public void setAttribute6(String attribute6) {
        this.attribute6 = attribute6;
    }
    public String getAttribute11() {
        return attribute11;
    }
    public void setAttribute11(String attribute11) {
        this.attribute11 = attribute11;
    }
    public String getAttribute7() {
        return attribute7;
    }
    public void setAttribute7(String attribute7) {
        this.attribute7 = attribute7;
    }
    public String getAttribute8() {
        return attribute8;
    }
    public void setAttribute8(String attribute8) {
        this.attribute8 = attribute8;
    }
    public String getAttribute9() {
        return attribute9;
    }
    public void setAttribute9(String attribute9) {
        this.attribute9 = attribute9;
    }
    public String getAttribute10() {
        return attribute10;
    }
    public void setAttribute10(String attribute10) {
        this.attribute10 = attribute10;
    }
    @Override
    public String toString() {
        return "ExamPaper{" +
                "attribute1='" + attribute1 + '\'' +
                ", attribute2='" + attribute2 + '\'' +
                ", attribute3='" + attribute3 + '\'' +
                ", attribute4='" + attribute4 + '\'' +
                ", attribute5='" + attribute5 + '\'' +
                ", attribute6='" + attribute6 + '\'' +
                ", attribute11='" + attribute11 + '\'' +
                ", attribute7='" + attribute7 + '\'' +
                ", attribute8='" + attribute8 + '\'' +
                ", attribute9='" + attribute9 + '\'' +
                ", attribute10='" + attribute10 + '\'' +
                '}';
    }
}
public class Client {
    public static void main(String[] args) {
        ExamPaper examPaper = new ExamPaper();
        examPaper.setAttribute1("1");
        examPaper.setAttribute4("4");
        examPaper.setAttribute2("2");
        examPaper.setAttribute5("50");
        System.out.println("源对象:"+examPaper.toString());
        ExamPaper copy = (ExamPaper)BeanUtils.copy(examPaper);
        System.out.println("copy对象:"+copy);
    }
}

2、通用实现:

抽象原型实现
public interface IPrototype<T> {
    T clone();
}
具体原型实现
public class ConcretePrototype implements IPrototype {
    private int age;
    private String name;
    private List<String> hobbies;
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<String> getHobbies() {
        return hobbies;
    }
    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }
    @Override
    public String toString() {
        return "ConcretePrototype{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", hobbies=" + hobbies +
                '}';
    }
    //这里可以使用set赋值,也可以模仿简单实现内通过反射来赋值
    @Override
    public ConcretePrototype clone() {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        concretePrototype.setAge(age);
        concretePrototype.setName(name);
        return concretePrototype;
    }
}
public class Client {
    public static void main(String[] args) {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        concretePrototype.setName("wangzx");
        concretePrototype.setAge(10);
        List<String> h = new ArrayList<>();
        h.add("打球");
        h.add("看电影");
        concretePrototype.setHobbies(h);
        System.out.println("源对象" + concretePrototype.toString());

        ConcretePrototype clone = concretePrototype.clone();
        clone.setName("lisi");
        h.add("上网");
        clone.setHobbies(h);

        System.out.println("克隆后的对象:" + clone.toString());
        //源对象名没有改变???
        System.out.println("克隆对象改名后源对象名:" + concretePrototype.toString());
        //源对象爱好改变
        System.out.println("克隆对象新增爱好后源对象爱好:" + concretePrototype.toString());
    }
}

优点:java自带的原型模式是基于内存二进制流的拷贝,比直接new一个对象性能上提升了许多。
可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,简化了创建过程
缺点:必须配备克隆或者可拷贝的方法,当对已有类进行改造的时候,需要修改代码,违背了开闭原则,深拷贝、浅拷贝需要运用得当

上一篇下一篇

猜你喜欢

热点阅读