原型模式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
原文地址:https://www.cnblogs.com/rouqinglangzi/p/6880731.html