原型模式

文章介绍了Java中的原型模式,用于高效地创建重复但内容基本相同的复杂对象。通过实现Cloneable接口,可以实现对象的浅拷贝和深拷贝,分别对应引用类型和整个对象结构的复制。文章还提供了示例代码,展示了如何实现深拷贝以及如何通过原型管理器进行对象的预创建和克隆,以提高程序性能。
摘要由CSDN通过智能技术生成

原型模式

创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,

应用场景

创建复杂的对象而且创建过程特别长,且内容基本都相同,
比如json的解析还原对象的过程,先将对象转化成json形式的字符串,然后再将字符串转化成对象,如果采用构造方法的方式进行创建,则需要了解每个函数的构造方法进行创建或者进行setter

优点

可以快速的相同的对象,性能比重新创建对象高

缺点

需要实现Cloneable接口,对于已经存在的类来说,改造成本会增大,会影响原来的逻辑

浅拷贝

浅拷贝是指在复制对象过程中,只将基础类型还包括String 以及基本类型的包装类型的对象复制过来,但是引用类型的还是指向原来对象的内存 ,因此两种对象中如果任意改变引用类型的对象的值,两边的值都会被改变,如果用== 或者equal来进行整个对象的比较地址值是不相同的

深拷贝

深拷贝是指在复制对象过程中,将新的对象完全开辟一个新的内存去存储新的对象,原来或者克隆对象的改变都不会引起双方值的变化,在java中使用流的方式来实现这种深拷贝

测试代码

公共对象

user类
package com.example.demo.study.prototype;

import java.io.*;

/**
 * @Author zhanpeng
 * @Date 2023/5/23 9:11
 */

public class User implements Cloneable, Serializable {

    private String name;

    private int age ;

    private Integer high;

    private Phone phone;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Integer getHigh() {
        return high;
    }

    public void setHigh(Integer high) {
        this.high = high;
    }

    public Phone getPhone() {
        return phone;
    }

    public void setPhone(Phone phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", high=" + high +
                ", phone=" + phone +
                '}';
    }

    @Override
    public User clone() {
        try {
            User clone = (User) super.clone();
            /*// 这一部分是将对象进行深拷贝,当调用clone的方法时默认返回的是深拷贝后的对象
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(this);
            objectOutputStream.flush();
            ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
            clone = (User)objectInputStream.readObject();
            objectInputStream.close();
            objectOutputStream.close();*/
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

}

phone 类
package com.example.demo.study.prototype;

import java.io.Serializable;

/**
 * @Author zhanpeng
 * @Date 2023/5/24 8:50
 */

public class Phone implements/* Cloneable*/ Serializable {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Phone{" +
                "name='" + name + '\'' +
                '}';
    }

   /* @Override
    public Phone clone() {
        try {
            Phone clone = (Phone) super.clone();
            // TODO: copy mutable state here, so the clone can't change the internals of the original
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }*/
}

测试代码

拷贝测试类,如果只需要浅拷贝,就使用上述代码即可,如果需要深拷贝 放开user类中在clone方法中注释的代码

    public static  void main(String[] args){

        //浅克隆
        User user = new User();
        user.setAge(3);
        user.setName("333");
        user.setHigh(130);
        Phone phone = new Phone();
        phone.setName("苹果");
        user.setPhone(phone);

        User clone = user.clone();
        clone.setAge(2);
        clone.setName("222");
        clone.setHigh(120);
        clone.getPhone().setName("安卓");
        /*Phone phone2 = new Phone();
        phone2.setName("安卓");
        clone.setPhone(phone2);*/

        System.out.println("clone.equals(user) = " + clone.equals(user));
        System.out.println(clone == user);

        System.out.println("user = " + user);
        System.out.println("clone = " + clone);
    }

测试结果

浅拷贝的测试结果,可以看到 引用类型的对象被变得完全一样了,但是其他的类型的都正常的改变了

clone.equals(user) = false
false
user = User{name='333', age=3, high=130, phone=Phone{name='安卓'}}
clone = User{name='222', age=2, high=120, phone=Phone{name='安卓'}}

深拷贝的测试结果,可以看到双方任意对象的改变都不会影响彼此

#深拷贝的测试结果
clone.equals(user) = false
false
user = User{name='333', age=3, high=130, phone=Phone{name='苹果'}}
clone = User{name='222', age=2, high=120, phone=Phone{name='安卓'}}

原型管理

简单原型管理

比如我需要创建一个User类,但是我不想在运行时在去创建,那样可能会很耗时,我想在加载的时候就创建成功,然后提供一个克隆方法来实现管理

package com.example.demo.study.prototype;

/**
 * @Author zhanpeng
 * @Date 2023/5/25 7:57
 */

public enum PrototypeManager {
    //一个单例模式的原型工厂,来控制克隆对象
    INSTANCE;

    private static final User user =  new User();

    //默认初始化一个user对象,用于提供复制
    static {
        user.setAge(3);
        user.setName("333");
        user.setHigh(130);
        Phone phone = new Phone();
        phone.setName("苹果");
        user.setPhone(phone);
    }

    //输出复制的对象的方法
    public  User getCloneUser() {
        return user.clone();
    }


}

测试
@Test
    public void test1 () {
        User cloneUser = PrototypeManager.INSTANCE.getCloneUser();
        System.out.println("cloneUser = " + cloneUser);
    }

测试结果
cloneUser = User{name='333', age=3, high=130, phone=Phone{name='苹果'}}

通用管理

这个管理器我想更通用一点,比如定义一个PEOPLE的接口,然后继承Cloneable,只要实现了POEPLE的类我都可以进行管理,这里我定义了一个Student 和一个Teacher老师类来实现PEOPLE这个接口然后进行原型管理

people接口
package com.example.demo.study.prototype;

/**
 * @Author zhanpeng
 * @Date 2023/5/25 8:07
 */

public interface People extends Cloneable{

    //定义一个 克隆people接口
    People clone() throws CloneNotSupportedException;
}

学生类
package com.example.demo.study.prototype;

/**
 * @Author zhanpeng
 * @Date 2023/5/25 8:15
 */

public class Student implements People{

    private String name;

    private int age ;

    private Integer high;

    private Phone phone;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Integer getHigh() {
        return high;
    }

    public void setHigh(Integer high) {
        this.high = high;
    }

    public Phone getPhone() {
        return phone;
    }

    public void setPhone(Phone phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", high=" + high +
                ", phone=" + phone +
                '}';
    }

    @Override
    public Student clone(){
        try {
            Student clone = (Student) super.clone();
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

老师类
package com.example.demo.study.prototype;

/**
 * @Author zhanpeng
 * @Date 2023/5/25 8:19
 */

public class Teacher implements People{

   private String name;

   private int age ;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   @Override
   public String toString() {
      return "Teacher{" +
              "name='" + name + '\'' +
              ", age=" + age +
              '}';
   }

   @Override
   public Teacher clone() throws CloneNotSupportedException {
      try {
         Teacher clone = (Teacher) super.clone();
         return clone;
      } catch (CloneNotSupportedException e) {
         throw new AssertionError();
      }
   }
}

原型管理器
package com.example.demo.study.prototype;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author zhanpeng
 * @Date 2023/5/25 7:57
 */

public enum PrototypeManager2 {
    INSTANCE;

    public enum PeopleType {
        STU,TEA;
    }
    //一个单例模式的原型工厂,来控制克隆对象

    private static final Map<String, People> clones =  new HashMap<String, People>();

    //初始化需要克隆的对象,此处展示的是简单对象,如果项目上有复制对象可以再启动环节就进行创建好,然后后续直接克隆使用
    static {
        Student student = new Student();
        student.setAge(8);
        student.setName("狗蛋");
        student.setHigh(130);
        Phone phone = new Phone();
        phone.setName("小苹果手机");
        student.setPhone(phone);
        clones.put(PeopleType.STU.name(), student);
        Teacher teacher = new Teacher();
        teacher.setAge(33);
        teacher.setName("小王老师");
        clones.put(PeopleType.TEA.name(), teacher);
    }

    //输出复制的对象的方法
    public People getClonePeople(PeopleType type) {
        try {
            return clones.get(type.name()).clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

}

测试类
@Test
    public void test2 () {
        People cloneStudent = PrototypeManager2.INSTANCE.getClonePeople(PrototypeManager2.PeopleType.STU);
        People cloneTeacher = PrototypeManager2.INSTANCE.getClonePeople(PrototypeManager2.PeopleType.TEA);
        System.out.println("cloneStudent = " + cloneStudent);
        System.out.println("cloneTeacher = " + cloneTeacher);
    }

测试结果
cloneStudent = Student{name='狗蛋', age=8, high=130, phone=Phone{name='小苹果手机'}}
cloneTeacher = Teacher{name='小王老师', age=33}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值