03-JAVA设计模式-原型模式

原型模式

什么是原型模式

Java原型模式(Prototype Pattern)是一种创建型设计模式,其核心理念在于通过复制(克隆)已有的对象来创建新的对象,而不是通过构造函数来创建。
该模式可以显著提高对象创建的效率,特别是在需要频繁创建对象或对象创建过程较为复杂的场景下。

在原型模式中,原型对象作为基础对象,其他对象通过复制这个原型对象来创建新的实例。复制过程可以是浅克隆或深克隆。

  • 浅克隆创建一个新对象,新对象的属性和原对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
  • 深克隆则更为彻底,不仅创建新对象,而且属性中引用的其他对象也会被克隆,不再指向原有对象的内存地址。

注意:发生浅拷贝主要针对数据类型为引用类型。

使用场景及特点

  • 当通过new产生一个对象需要非常反锁的数据准备及访问权限时,则可以使用原型模式
  • 就是java中的克隆技术,以某个对象为原型,复制出新的对象。显然,新的对象具备原型对象的特点。
    • 优势:效率高(直接克隆,避免了重新执行构造过程的步骤)
  • 克隆类似于new,但是不同于new。new创建新的对象属性采用的是默认值,克隆对象的属性完全与原型对象相同,并且克隆出的新对象改变不会影响原型对象,然后再修改克隆对象的值。

原型模式实现

  • Cloneable接口和clone方法
  • 原型模式中实现起来最为困难的地方就是内存复制操作,然而在Java中提供了对象的clone()方法替我门做了绝大部分事情。

案例

使用原型模式,必须实现Cloneable接口,重写protected Object clone()方法

浅拷贝

Address.java

//地址
public class Address {
  private String city;

  public Address(String city) {
    this.city = city;
  }

  public void setCity(String city) {
    this.city = city;
  }

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

Person.java

// 浅拷贝
// 实现Cloneable接口 重写protected Object clone()方法
public class Person implements Cloneable{
  private String name;

  private Address address;

  public Person(String name, Address address) {
    this.name = name;
    this.address = address;
  }

  public Address getAddress() {
    return address;
  }

  public void setAddress(Address address) {
    this.address = address;
  }

  @Override
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();   // 默认浅拷贝
  }

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

TestClient.java

public class TestClient {

    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person("张三",new Address("北京"));
        Person clone = (Person) person.clone();
        System.out.printf("浅拷贝-原型对象:%s%n",person);
        System.out.printf("浅拷贝-拷贝对象值:%s%n",clone);

        System.out.println("======修改原型对象-address======");
        person.getAddress().setCity("重庆");
        System.out.printf("浅拷贝-原型对象:%s%n",person);
        System.out.printf("浅拷贝-拷贝对象值:%s%n",clone);

        System.out.println("======修改拷贝对象-address======");
        clone.getAddress().setCity("广州");
        System.out.printf("浅拷贝-原型对象:%s%n",person);
        System.out.printf("浅拷贝-拷贝对象值:%s%n",clone);
    }
}

执行结果:

在这里插入图片描述

图解

在这里插入图片描述

浅拷贝时,当修改原型对象时,拷贝的对象引用仍然指向原型对象的引用,因此修改原型对象,会导致拷贝对象的值发生改变
修改拷贝对象的属性时,则会在堆内存中创建一个新的地址存储新设置的值,拷贝对象引用指向新的引用地址,但不会改变原型对象的引用地址。

深拷贝

Address.java 实现Cloneable接口,重新clone()

// 地址
public class Address implements Cloneable{
    private String city;

    public Address(String city) {
        this.city = city;
    }

    public void setCity(String city) {
        this.city = city;
    }

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

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

修改Person clone()方法

// 深拷贝
public class Person implements Cloneable{
    private String name;

    private Address address;

    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person clone = (Person) super.clone();
        clone.address = (Address) this.getAddress().clone();
        return clone;
    }

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

TestClient2.java

public class TestClient2 {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person("张三",new Address("北京"));
        Person clone = (Person) person.clone();
        System.out.printf("深拷贝-原型对象:%s%n",person);
        System.out.printf("深拷贝-拷贝对象值:%s%n",clone);

        System.out.println("======修改原型对象-address======");
        person.getAddress().setCity("重庆");
        System.out.printf("深拷贝-原型对象:%s%n",person);
        System.out.printf("深拷贝-拷贝对象值:%s%n",clone);

        System.out.println("======修改拷贝对象-address======");
        clone.getAddress().setCity("广州");
        System.out.printf("深拷贝-原型对象:%s%n",person);
        System.out.printf("深拷贝-拷贝对象值:%s%n",clone);
    }
}

执行结果:

在这里插入图片描述

图解

在这里插入图片描述

利用序列化和反序列化完成深克隆

通过序列化及反序列化实现深克隆必须实现Serializable接口
Person.java

public class Person implements Serializable {

  private String name;

  private Address address;

  public Person(String name, Address address) {
    this.name = name;
    this.address = address;
  }

  public Address getAddress() {
    return address;
  }

  public void setAddress(Address address) {
    this.address = address;
  }

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

Address.java

// 地址
public class Address implements Serializable {

    private String city;

    public Address(String city) {
        this.city = city;
    }

    public void setCity(String city) {
        this.city = city;
    }

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

TestClient3.java

public class TestClient3 {
    public static void main(String[] args) throws CloneNotSupportedException, Exception {
        Person person = new Person("张三",new Address("北京"));
        // 通过序列化 反序列化实现深拷贝

        byte[] bytes = null;
        Person clone = null;

        // 序列化
        try( ByteArrayOutputStream baos = new ByteArrayOutputStream();
             ObjectOutputStream oos = new ObjectOutputStream(baos);){
            oos.writeObject(person);
            bytes = baos.toByteArray();
        }

        // 反序列化
        try( ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
             ObjectInputStream ois = new ObjectInputStream(bais);){
            clone = (Person) ois.readObject();
        }

        System.out.printf("深拷贝-原型对象:%s%n",person);
        System.out.printf("深拷贝-拷贝对象值:%s%n",clone);

        System.out.println("======修改原型对象-address======");
        person.getAddress().setCity("重庆");
        System.out.printf("深拷贝-原型对象:%s%n",person);
        System.out.printf("深拷贝-拷贝对象值:%s%n",clone);

        System.out.println("======修改拷贝对象-address======");
        clone.getAddress().setCity("广州");
        System.out.printf("深拷贝-原型对象:%s%n",person);
        System.out.printf("深拷贝-拷贝对象值:%s%n",clone);
    }
}

执行结果:

在这里插入图片描述

gitee源码

git clone https://gitee.com/dchh/JavaStudyWorkSpaces.git

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java设计模式是一组经过实践验证的面向对象设计原则和模式,可以帮助开发人员解决常见的软件设计问题。下面是常见的23种设计模式: 1. 创建型模式(Creational Patterns): - 工厂方法模式(Factory Method Pattern) - 抽象工厂模式(Abstract Factory Pattern) - 单例模式(Singleton Pattern) - 原型模式(Prototype Pattern) - 建造者模式(Builder Pattern) 2. 结构型模式(Structural Patterns): - 适配器模式(Adapter Pattern) - 桥接模式(Bridge Pattern) - 组合模式(Composite Pattern) - 装饰器模式(Decorator Pattern) - 外观模式(Facade Pattern) - 享元模式(Flyweight Pattern) - 代理模式(Proxy Pattern) 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility Pattern) - 命令模式(Command Pattern) - 解释器模式(Interpreter Pattern) - 迭代器模式(Iterator Pattern) - 中介者模式(Mediator Pattern) - 备忘录模式(Memento Pattern) - 观察者模式(Observer Pattern) - 状态模式(State Pattern) - 策略模式(Strategy Pattern) - 模板方法模式(Template Method Pattern) - 访问者模式(Visitor Pattern) 4. 并发型模式(Concurrency Patterns): - 保护性暂停模式(Guarded Suspension Pattern) - 生产者-消费者模式(Producer-Consumer Pattern) - 读写锁模式(Read-Write Lock Pattern) - 信号量模式(Semaphore Pattern) - 线程池模式(Thread Pool Pattern) 这些设计模式可以根据问题的特点和需求来选择使用,它们提供了一些可复用的解决方案,有助于开发高质量、可维护且易于扩展的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丨Anna丨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值