设计模式三(原型模式)

在开发过程中,创建多个数据相同的对象,每次new都开销比较大,在这里可以使用对象克隆,以先创建的原型对象为模板进行对象的复制。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用

浅克隆

在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址

复制代码
 
java 复制代码
public class Person implements  Cloneable{
 ​
      int num;
      String name;
 ​
     public Person() {
     }
 ​
     public Person(int num, String name) {
         this.num = num;
         this.name = name;
     }
 ​
     public int getNum() {
         return num;
     }
 ​
     public void setNum(int num) {
         this.num = num;
     }
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         this.name = name;
     }
 ​
 ​
 ​
     @Override
     protected Person clone() throws CloneNotSupportedException {
         Person person = (Person)super.clone();
         return person;
     }
 ​
     @Override
     public String toString() {
         return "Person{" +
                 "num=" + num +
                 ", name='" + name + '\'' +
                 '}';
     }
 }
java 复制代码
 public class Test {
 ​
     public static void main(String[] args) throws CloneNotSupportedException {
 ​
         Person p1 = new Person(100,"jim");
         Person p2 =p1.clone();//clone方法 返回一个新对象
         p2.name = "tom";
         System.out.println(p1);//100 ,jim
         System.out.println(p2);//100 tom
 ​
         System.out.println(p1==p2);//false
 ​
     }
 }

深克隆

多层克隆

在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制

java 复制代码
 public class Person implements  Cloneable{
 ​
      int num;
      String name;
      Address address;
 ​
     public Person() {
 ​
     }
 ​
     public Person(int num, String name) {
         this.num = num;
         this.name = name;
     }
 ​
     public int getNum() {
         return num;
     }
 ​
     public void setNum(int num) {
         this.num = num;
     }
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         this.name = name;
     }
 ​
     public Address getAddress() {
         return address;
     }
 ​
     public void setAddress(Address address) {
         this.address = address;
     }
 ​
     @Override
     protected Person clone() throws CloneNotSupportedException {
         Person person = (Person)super.clone();
         person.address = address.clone();   //深度复制  联同person中关联的对象也一同克隆.
         return person;
     }
 ​
     @Override
     public String toString() {
         return "Person{" +
                 "num=" + num +
                 ", name='" + name + '\'' +
                 ", address=" + address +
                 '}';
     }
 }
 ​
java 复制代码
 public class Address  implements Cloneable{
 ​
      String  address;
 ​
     public String getAddress() {
         return address;
     }
 ​
     public void setAddress(String address) {
         this.address = address;
     }
 ​
     @Override
     public String toString() {
         return "Address{" +
                 "address='" + address + '\'' +
                 '}';
     }
 ​
      @Override
     protected Address clone() throws CloneNotSupportedException {
         return (Address) super.clone();
     }
 }

序列化

复制代码
 
java 复制代码
public class Address  implements Serializable {
 ​
      String  address;
 ​
     public String getAddress() {
         return address;
     }
 ​
     public void setAddress(String address) {
         this.address = address;
     }
 ​
     @Override
     public String toString() {
         return "Address{" +
                 "address='" + address + '\'' +
                 '}';
     }
 ​
 }
复制代码
 
java 复制代码
public class Person implements Serializable {
 ​
      int num;
      String name;
      Address address;
 ​
     public Person() {
     }
 ​
     public Person(int num, String name) {
         this.num = num;
         this.name = name;
     }
 ​
     public int getNum() {
         return num;
     }
 ​
     public void setNum(int num) {
         this.num = num;
     }
 ​
     public String getName() {
         return name;
     }
 ​
     public void setName(String name) {
         this.name = name;
     }
 ​
     public Address getAddress() {
         return address;
     }
 ​
     public void setAddress(Address address) {
         this.address = address;
     }
 ​
     /**
      * 自定义克隆方法
      * @return
      */
     public Person myclone() {
             Person person = null;
               try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
                      ByteArrayOutputStream baos = new ByteArrayOutputStream();
                       ObjectOutputStream oos = new ObjectOutputStream(baos);
                       oos.writeObject(this);
             // 将流序列化成对象
                     ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                      ObjectInputStream ois = new ObjectInputStream(bais);
                      person = (Person) ois.readObject();
                   } catch (IOException e) {
                      e.printStackTrace();
                   } catch (ClassNotFoundException e) {
                      e.printStackTrace();
                  }
              return person;
           }
 ​
 ​
     @Override
     public String toString() {
         return "Person{" +
                 "num=" + num +
                 ", name='" + name + '\'' +
                 ", address=" + address +
                 '}';
     }
 }

练习

题目页面 (kamacoder.com)

java 复制代码
import java.util.Scanner;

public class Main {

    public static void main(String[] args) throws CloneNotSupportedException {
        Scanner scanner = new Scanner(System.in);
        int num = scanner.nextInt();
        while(num-->0){
            String color = scanner.next();
            int width = scanner.nextInt();
            int height = scanner.nextInt();
            Prototype prototype = new Prototype(color, width, height);
            Prototype clone = prototype.clone();
            System.out.println(clone.toString());
        }
    }
}

class Prototype implements Cloneable{
    private String color;
    private int width;
    private int height;

    public Prototype(String color, int width, int height) {
        this.color = color;
        this.width = width;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Color: " + color + ", Width: " + width + ", Height: " + height;
    }

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


}
相关推荐
Zane19942 小时前
Lock 接口与 AQS 核心原理:手写理解一把可重入锁是怎么运作的
java·后端
Full Stack Developme2 小时前
SpringBoot 整合 Druid 并列出参数清单
java·spring boot·后端
caishenzhibiao2 小时前
顺势交易矩阵主图 同花顺期货通指标
java·c语言·c#
梓仁沐白2 小时前
【Agent 设计模式】多智能体协作
microsoft·设计模式·php
我命由我123452 小时前
Android 开发 - 广播组件(标准广播、有序广播、静态注册广播、分钟到达广播、网络变更广播...)
android·java·开发语言·网络·java-ee·android studio·android-studio
周航宇JoeZhou2 小时前
JP3-2-1-MyItem项目简介
java·ai·springboot·环境搭建·项目·管理·springai
努力学习的廖同学2 小时前
前端进阶-设计模式
设计模式
lemon_sjdk3 小时前
从 ServletRequest 到 Spring 抽象:Web 请求的底层基石与演化
java·前端·spring
唐青枫3 小时前
Java Reactor Netty 实战详解:从响应式 HTTP 到 TCP 长连接
java·netty
SamDeepThinking3 小时前
现场重构一段代码,展示什么叫「好代码,都在表达自己的意图」
java·后端·程序员