• 原型模式prototype


    一、什么是原型模式

    原型模式是一种对象创建型模式,它采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例,具有与原型一样的数据

    二、原型模式的特点

    1.由原型对象自身创建目标对象。也就是说,对象创建这一动作发自原型对象本身。

    2.目标对象是原型对象的一个克隆。也就是说,通过Prototype模式创建的对象,不仅仅与原型对象具有相同的结构,还与原型对象具有相同的值。

    3.根据对象克隆深度层次的不同,有浅克隆深克隆

    三、原型模式应用场景

    - 在创建对象的时候,我们不只是希望被创建的对象继承其基类的基本结构,还希望继承原型对象的数据。

    - 希望对目标对象的修改不影响既有的原型对象(深度克隆的时候可以完全互不影响)。

    - 隐藏克隆操作的细节。很多时候,对对象本身的克隆需要涉及到类本身的数据细节。

    四、例子

    Person类实现了Clonable接口,该接口和Serializable一样,仅仅是一个标志,表明该类可以被克隆。同时它提供了一个clone方法,需要注意的是clone方法是Object中的方法,Person进行了重写。

    public class Person implements Cloneable{
        private String name;
        private int age;
        private String sex;

    public Person clone() { try { Person person = (Person)super.clone();
    return person; } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } //省略了setter和getter }
    public class MainClass {
        public static void main(String[] args) {
            //Person1
            Person person1 = new Person();
            person1.setName("lifengxing");//name
            person1.setAge(30);//age
            person1.setSex("男");//sex
            List<String> friends = new ArrayList<String>();
            friends.add("James");
            friends.add("Yao");
            person1.setFriends(friends);//friends
    
            //0.克隆Person1得到person2
            Person person2 = person1.clone();
            
            //1.验证person1和person2的所有属性值
            System.out.println(person2.getName());//lifengxing
            System.out.println(person2.getAge());//30
            System.out.println(person2.getSex());//
            System.out.println(person2.getFriends());//[James, Yao]
            
            //2.验证基本属性
            //person1变性
            person1.setSex("女");
            System.out.println("person1变性为"+person1.getSex());//性别变为女
            System.out.println("person2依旧为"+person2.getSex());//性别仍为男
            
            //3.验证引用属性
            //person1多了一个朋友kitty
            List<String> li = person1.getFriends();
            li.add("kitty");
            person1.setFriends(li);
            System.out.println("person1现在的朋友:"+person1.getFriends());//[James, Yao, kitty]
            System.out.println("person2现在的朋友:"+person2.getFriends());//[James, Yao, kitty]
    
    }

    0处调用clone方法生成了新的对象,1处通过打印结果可知克隆后的对象与原对象属性值完全一样。

    但是仅仅通过打印结果相同并不能说明person2就一定是引用了一个新创建的对象,难道就不可能是person2指向了person1吗,也就是Person person2=person1;

    于是,2处进行验证:

      将person1进行变性,打印结果显示虽然person1确实变性成功,但是person2根本不受影响。这也就说明clone操作一定是创建了新的对象。

      3处进一步验证:person1由于变性后魅力大增,结识了新的朋友kitty,打印结果发现person2也多了一个kitty朋友。为什么跟上面的不一致了呢?

    这里涉及了深克隆和浅克隆的知识。

    要想对person1进行深克隆,只需要在clone方法中手动对引用(复杂)类型的属性手动克隆一下就行了。

    public class Person implements Cloneable{
        private String name;
        private int age;
        private String sex;
        private List<String> friends;
        
        public Person clone() {
            try {
                Person person  = (Person)super.clone();
                //a.手动对引用类型的属性friends进行克隆
                List<String> clonefriends = new ArrayList<String>();
                clonefriends.addAll(this.getFriends());
                person.setFriends(clonefriends);
                return  person;
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    再次运行程序,结果就是person2完全不受person1影响了,也就是person2对person1进行了深克隆。

     ……更多设计模式的内容,可以访问Refactoring.Guru
  • 相关阅读:
    Python-Matplotlib 12 多图figure
    Python-Matplotlib 11 子图-subplot
    Python Day16
    Python Day15
    Python Day13-14
    Python Day12
    Python Day11
    Python Day9-10
    Python Day8
    Python Day8
  • 原文地址:https://www.cnblogs.com/rouqinglangzi/p/6880731.html
Copyright © 2020-2023  润新知