美文网首页
原型模式

原型模式

作者: Teemo_fca4 | 来源:发表于2020-05-07 21:07 被阅读0次

    假设现在有个需求,根据已有的一个对象,复制N个实体,要求复制后的对象属性一致,传统代码可能是这么写。

        public static void main(String[] args) {
            //传统的方法
            Sheep sheep = new Sheep("tom", 1, "白色");
            
            Sheep sheep2 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
            Sheep sheep3 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
            Sheep sheep4 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
            Sheep sheep5 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
            //....
            
            System.out.println(sheep);
            System.out.println(sheep2);
            System.out.println(sheep3);
            System.out.println(sheep4);
            System.out.println(sheep5);
            //...
        }
    

    这种方式的优点是简单,容易理解,但是这种方法,如果被复制的对象比较复杂的时候,效率很低,代码也随之复杂起来。
    改进:
    Java中的Object类中有clone方法,他可以将对象复制一份,但是 需要被复制的类必须实现Cloneable接口,表示该类具有复制的能力。

    public class Sheep implements Cloneable {
        private String name;
        private int age;
        private String color;
        private String address = "蒙古羊";
        public Sheep friend; //是对象, 克隆是会如何处理?
        public Sheep(String name, int age, String color) {
            super();
            this.name = name;
            this.age = age;
            this.color = color;
        }
        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 String getColor() {
            return color;
        }
        public void setColor(String color) {
            this.color = color;
        }
        
        @Override
        public String toString() {
            return "Sheep [name=" + name + ", age=" + age + ", color=" + color + ", address=" + address + "]";
        }
        
        @Override
        protected Object clone()  {
            
            Sheep sheep = null;
            try {
                sheep = (Sheep)super.clone();//这里调用父类的clone方法来实现复制
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
            return sheep;
        }
    }
    
        public static void main(String[] args) {
            System.out.println("原型模式完成对象的创建");
            Sheep sheep = new Sheep("tom", 1, "白色");
            sheep.friend = new Sheep("jack", 2, "黑色");
            
            Sheep sheep2 = (Sheep)sheep.clone(); //克隆
            Sheep sheep3 = (Sheep)sheep.clone(); //克隆
            Sheep sheep4 = (Sheep)sheep.clone(); //克隆
            Sheep sheep5 = (Sheep)sheep.clone(); //克隆
            
            System.out.println("sheep2 =" + sheep2 + "sheep2.friend=" + sheep2.friend.hashCode());
            System.out.println("sheep3 =" + sheep3 + "sheep3.friend=" + sheep3.friend.hashCode());
            System.out.println("sheep4 =" + sheep4 + "sheep4.friend=" + sheep4.friend.hashCode());
            System.out.println("sheep5 =" + sheep5 + "sheep5.friend=" + sheep5.friend.hashCode());
        }
    

    Spring中的原型模式调用

            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
            Object bean = applicationContext.getBean("id01");
    追踪getBean源码,AbstractBeanFactory.getBean调用doGetBean,doGetBean中有以下代码,原型模式
                    if (mbd.isSingleton()) {
                        sharedInstance = this.getSingleton(beanName, () -> {
                            try {
                                return this.createBean(beanName, mbd, args);
                            } catch (BeansException var5) {
                                this.destroySingleton(beanName);
                                throw var5;
                            }
                        });
                        bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    } else if (mbd.isPrototype()) {
                        var11 = null;
    
                        Object prototypeInstance;
                        try {
                            this.beforePrototypeCreation(beanName);
                            prototypeInstance = this.createBean(beanName, mbd, args);
                        } finally {
                            this.afterPrototypeCreation(beanName);
                        }
    
                        bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                    } else 
    
    
    深拷贝与浅拷贝

    深拷贝:对于成员变量是基本类型浅拷贝会直接复制一份值出来,对于引用类型(String呀,数组呀,类对象呀)浅拷贝会复制地址的值,对于上面的拷贝,可以看出来 Object中的clone使用的是浅拷贝。
    深拷贝:对于引用类型,也重新复制一个对象出来,这样会整改对象都会拷贝出来。
    深拷贝实现1:重写clone方法(不推荐,不能做到完全深拷贝)
    深拷贝实现2:序列化(推荐)

    public class DeepCloneableTarget implements Serializable, Cloneable {
        private static final long serialVersionUID = 1L;
    
        private String cloneName;
    
        private String cloneClass;
    
        //构造器
        public DeepCloneableTarget(String cloneName, String cloneClass) {
            this.cloneName = cloneName;
            this.cloneClass = cloneClass;
        }
    
        //因为该类的属性,都是String , 因此我们这里使用默认的clone完成即可
        protected Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }
    
    public class DeepProtoType implements Serializable, Cloneable{
        
        public String name; //String 属性
        public DeepCloneableTarget deepCloneableTarget;// 引用类型
        public DeepProtoType() {
            super();
        }
        
        //深拷贝 - 方式 1 使用clone 方法
        @Override
        protected Object clone() throws CloneNotSupportedException {
            Object deep = null;
            //这里完成对基本数据类型(属性)和String的克隆
            deep = super.clone(); 
            //对引用类型的属性,进行单独处理
            DeepProtoType deepProtoType = (DeepProtoType)deep;
            deepProtoType.deepCloneableTarget  = (DeepCloneableTarget)deepCloneableTarget.clone();
            return deepProtoType;
        }
        
        //深拷贝 - 方式2 通过对象的序列化实现 (推荐)
        public Object deepClone() {
            //创建流对象
            ByteArrayOutputStream bos = null;
            ObjectOutputStream oos = null;
            ByteArrayInputStream bis = null;
            ObjectInputStream ois = null;
            try {
                //序列化
                bos = new ByteArrayOutputStream();
                oos = new ObjectOutputStream(bos);
                oos.writeObject(this); //当前这个对象以对象流的方式输出
                
                //反序列化
                bis = new ByteArrayInputStream(bos.toByteArray());
                ois = new ObjectInputStream(bis);
                DeepProtoType copyObj = (DeepProtoType)ois.readObject();
                
                return copyObj;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            } finally {
                //关闭流
                try {
                    bos.close();
                    oos.close();
                    bis.close();
                    ois.close();
                } catch (Exception e2) {
                    System.out.println(e2.getMessage());
                }
            }
        }
    }
    
        public static void main(String[] args) throws Exception {
            DeepProtoType p = new DeepProtoType();
            p.name = "宋江";
            p.deepCloneableTarget = new DeepCloneableTarget("大牛", "小牛");
            
            //方式1 完成深拷贝
            
    //      DeepProtoType p2 = (DeepProtoType) p.clone();
    //      
    //      System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
    //      System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
        
            //方式2 完成深拷贝
            DeepProtoType p2 = (DeepProtoType) p.deepClone();
            
            System.out.println("p.name=" + p.name + "p.deepCloneableTarget=" + p.deepCloneableTarget.hashCode());
            System.out.println("p2.name=" + p.name + "p2.deepCloneableTarget=" + p2.deepCloneableTarget.hashCode());
        }
    

    相关文章

      网友评论

          本文标题:原型模式

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