设计模式三(原型模式)

在开发过程中,创建多个数据相同的对象,每次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();
    }


}
相关推荐
一起养小猫11 小时前
LeetCode100天Day6-回文数与加一
java·leetcode
程序员小假12 小时前
我们来说一下 MySQL 的慢查询日志
java·后端
独自破碎E12 小时前
Java是怎么实现跨平台的?
java·开发语言
To Be Clean Coder12 小时前
【Spring源码】从源码倒看Spring用法(二)
java·后端·spring
xdpcxq102913 小时前
风控场景下超高并发频次计算服务
java·服务器·网络
想用offer打牌13 小时前
你真的懂Thread.currentThread().interrupt()吗?
java·后端·架构
橘色的狸花猫13 小时前
简历与岗位要求相似度分析系统
java·nlp
独自破碎E13 小时前
Leetcode1438绝对值不超过限制的最长连续子数组
java·开发语言·算法
用户917439653913 小时前
Elasticsearch Percolate Query使用优化案例-从2000到500ms
java·大数据·elasticsearch
yaoxin52112313 小时前
279. Java Stream API - Stream 拼接的两种方式:concat() vs flatMap()
java·开发语言