美文网首页
原型模式详解

原型模式详解

作者: 奋斗的韭菜汪 | 来源:发表于2020-06-16 20:29 被阅读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一个对象性能上提升了许多。
    可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,简化了创建过程
    缺点:必须配备克隆或者可拷贝的方法,当对已有类进行改造的时候,需要修改代码,违背了开闭原则,深拷贝、浅拷贝需要运用得当

    相关文章

      网友评论

          本文标题:原型模式详解

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