设计模式-原型模式

目录

🧂1.原型设计模式介绍

🌭2.浅拷贝

🥓3.深拷贝


1.原型设计模式介绍

  • 原型模式:是用于创建重复的对象,同时又能保证性能,属于创建型模式。
  • 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。
  • 类型:浅拷贝和深拷贝
  • 核心组成
  • 1.Prototype: 声明克隆方法的接口,是所有具体原型类的公共父类,Cloneable接口
  • 2.ConcretePrototype:具体原型类
  • 3.Client: 让一个原型对象克隆自身从而创建一个新的对象
  • 应用场景
  • 1.一个对象多个修改者的场景。
  • 2.通过 new 产生一个对象需要非常繁琐的数据准备或访问权限
  • 3.如果系统要保存对象的状态,做备份使用

2.浅拷贝

要想实现对象拷贝,就必须实现Cloneable接口,并且实现clone()克隆方法。

java 复制代码
public class Student implements Cloneable{
    private String age;
    private String name;

    private List<String> hobby=new ArrayList<>();

    public Student() {
        System.out.println("构造器被调用~");
    }

    public List<String> getHobby() {
        return hobby;
    }

    public void setHobby(List<String> hobby) {
        this.hobby = hobby;
    }

    public String getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    /**
     * 实现克隆方法-浅拷贝
     *
     * @return
     * @throws CloneNotSupportedException
     */
    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }


    /**
     * toString方法,方便查询
     *
     * @return
     */
    @Override
    public String toString() {
        return "Student{" +
                "age='" + age + '\'' +
                ", name='" + name + '\'' +
                ", hobby=" + hobby +
                '}';
    }
}

创建学生1并设置相关属性,通过s1克隆s2,只修改姓名和爱好

java 复制代码
public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student s1 = new Student();
        s1.setAge("18");
        s1.setName("小张");
       s1.getHobby().add("ccc");


        Student s2 = s1.clone();
        s2.setName("小小张");
        s2.getHobby().add("bbb");
        System.out.println("浅拷贝:"+s1.toString());
        System.out.println("浅拷贝:"+s2.toString());
    }
}

发现年龄不变和爱好,姓名改变

通过debug发现,s1和s2属性hobby的地址一样

上面拷贝模式属于浅拷贝

  • 如果原型对象的成员变量是基本数据类型(int, double, byte, boolean, char等) ,将复制一份给克隆对象;
  • 如果原型对象的成员变量是引用数据类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向****相同的内存地址
  • 通过覆盖object类的clone()方法可以实现浅克隆

3.深拷贝

无论原型对象的成员变量是基本数据类型还是引用类型,都将复制一份给克隆对象,如果需要实现深克隆,可以通过**序列化(Serializable)**等方式来实现

要想实现深拷贝 需要实现Serializable接口,实现序列化和反序列化

java 复制代码
public class Student implements Serializable {
    private String age;
    private String name;

    private List<String> hobby=new ArrayList<>();

    public Student() {
        System.out.println("构造器被调用~");
    }

    public List<String> getHobby() {
        return hobby;
    }

    public void setHobby(List<String> hobby) {
        this.hobby = hobby;
    }

    public String getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

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

    /**
     * 实现克隆方法-深拷贝
     * @return
     */
    public Student deepClone() {
        try {
            //输出  序列化
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(this);

            //输出  序列化
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            Student copyStudent = (Student) ois.readObject();
            return copyStudent;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * toString方法,方便查询
     *
     * @return
     */
    @Override
    public String toString() {
        return "Student{" +
                "age='" + age + '\'' +
                ", name='" + name + '\'' +
                ", hobby=" + hobby +
                '}';
    }
}

修改姓名和爱好

java 复制代码
public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student s1 = new Student();
        s1.setAge("18");
        s1.setName("小张");
       s1.getHobby().add("aaa");


        Student s2 = s1.deepClone();
        s2.setName("小小张");
        s2.getHobby().add("bbb");
        System.out.println("深拷贝:"+s1.toString());
        System.out.println("深拷贝:"+s2.toString());
    }
}

发现hobby的地址不同,并且hobby的值也不同

优点:

  • 性能提高:当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,可以提高新实例的创建效率
  • 可辅助实现撤销操作,使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用恢复到历史状态

缺点:

  • 需要为每一个类配备一个克隆方法,对已有的类进行改造时,需要修改源代码,违背了"开闭原则
  • 必须实现 Cloneable 接口或Serializable接口
相关推荐
涡能增压发动积13 小时前
同样的代码循环 10次正常 循环 100次就抛异常?自定义 Comparator 的 bug 让我丢尽颜面
后端
云烟成雨TD13 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
Wenweno0o13 小时前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
行乾13 小时前
鸿蒙端 IMSDK 架构探索
架构·harmonyos
于慨13 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz13 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
swg32132113 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
tyung13 小时前
一个 main.go 搞定协作白板:你画一笔,全世界都看见
后端·go
gelald13 小时前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川13 小时前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java