JAVA知识体系之设计模式篇(二)——原型模式

1、原型模式概述

  原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。——百度百科

2、原型模式实现方式(浅克隆和深克隆)

1、Work类

package com.parttern.prototype;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.Serializable;

@Getter
@Setter
@ToString
public class Work implements Serializable, Cloneable {

    String name;

    String location;

    @Override
    protected Work clone() throws CloneNotSupportedException {
        return (Work)super.clone();
    }
}

2、Person类(原型类)

package com.parttern.prototype;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Getter
@Setter
@ToString
public class Person implements Cloneable, Serializable{

    private String name;

    private int age;

    private Work work;

    private List<String> hobbyList;

    /**
     * 1、浅克隆,仅拷贝基础类型及String,无法拷贝对象中的对象
     */
    @Override
    protected Person clone() throws CloneNotSupportedException {
        return (Person)super.clone();
    }

    /**
     * 2、深克隆1,其实是对对象中的每个对象进行浅拷贝,代码量较多且不易于维护
     * 此外,像List这种无法重写实现Cloneable接口的类无法实现直接克隆,除非new对象手工实现
     */
    public Person deepClone1() {
        try {
            Work work1 = this.work.clone();
            Person person = (Person)super.clone();
            person.setWork(work1);
/*            List<String> hobbyList1 = new ArrayList<>(this.getHobbyList());
            person.setHobbyList(hobbyList1);*/
            return person;
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return new Person();
    }

    /**
     * 3、深克隆2,采用序列化反序列化的形式克隆对象,一劳永逸
     */
    public Person deepClone2() {

        Person person = null;
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person"));
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person"));) {
            oos.writeObject(this);
            person = (Person)ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return person;
    }
}

3、测试类PrototypeDemo

package com.parttern.prototype;

import java.util.ArrayList;
import java.util.List;

public class PrototypeDemo {

    public static void main(String[] args) {
        System.out.println("SimpleClone:");
        simpleClone();
        System.out.println("DeepClone1:");
        deepClone1();
        System.out.println("DeepClone2:");
        deepClone2();
    }
    
    private static void simpleClone(){
        Person person1 = initPerson();
        Person person2 = null;
        try {
            person2 = modPerson(person1.clone());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        printPerson(person1, person2);
    }


    private static void deepClone1(){
        Person person1 = initPerson();
        Person person2 = modPerson(person1.deepClone1());
        printPerson(person1, person2);
    }

    private static void deepClone2(){
        Person person1 = initPerson();
        Person person2 = modPerson(person1.deepClone2());
        printPerson(person1, person2);
    }

    private static Person initPerson(){
        Person person = new Person();
        person.setName("zhangsan");
        person.setAge(20);
        Work work = new Work();
        work.setName("ICBC");
        work.setLocation("Hangzhou");
        person.setWork(work);
        List<String> hobbyList = new ArrayList<>();
        hobbyList.add("basketball");
        hobbyList.add("violin");
        person.setHobbyList(hobbyList);
        return person;
    }

    private static Person modPerson(Person person){
        person.setAge(30);
        person.setName("lisilisi");
        person.getWork().setName("Bestpay");
        person.getWork().setLocation("Shanghai");
        person.getHobbyList().add("reading");
        return person;
    }

    private static void printPerson(Person person1, Person person2){
        System.out.println(person1);
        System.out.println(person2);
    }
}

4、输出结果:

SimpleClone:
Person(name=zhangsan, age=20, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])
Person(name=lisilisi, age=30, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])
DeepClone1:
Person(name=zhangsan, age=20, work=Work(name=ICBC, location=Hangzhou), hobbyList=[basketball, violin, reading])
Person(name=lisilisi, age=30, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])
DeepClone2:
Person(name=zhangsan, age=20, work=Work(name=ICBC, location=Hangzhou), hobbyList=[basketball, violin])
Person(name=lisilisi, age=30, work=Work(name=Bestpay, location=Shanghai), hobbyList=[basketball, violin, reading])

总结:
1、SimpleClone只能简单复制基本属性和String,对于引用属性实际上还是指向同一个对象。所以work和hobbyList都相等。
2、DeepClone1通过对引用类重写clone来实现,这种方式有两种问题,一是如果该类增加一个对象,就需要增加对应的clone逻辑,代码复杂;二是对于List这种无法实现Cloneable接口的类无法重写,只能通过new对象然后addAll来实现,违背原型模式的初衷。所以Work不相等但是hobbyList还是相等。
3、通过序列化反序列化来生成一个新的对象,两个对象及引用的对象内存地址完全不同。所以hobbyList也不相等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值