原型模式

原型模式是一种创建型模式,它的工作原理很简单,将一个对象克隆给另一个需要使用它的对象,这里通过克隆方法创建出来的对象是一个全新的对象,他们在内存中拥有新的地址,通常对克隆所产生的对象进行修改不会对原型对象造成任何影响。

原型模式的结构

**1.prototype(抽象原型类):**它是声明克隆方法的接口,是所有具体原型类的公共父类,它可以是抽象类,也可以是抽象接口,甚至还可以是具体实现类
**2.ConcretePrototype(具体原型类):**它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象
**3.Client(客户类):**在客户类中,让一个原型对象克隆自身从而创建一个新的对象,只需要直接实例化或通过工厂方法等方式创建一个新的对象,再通过调用该对象的克隆方法可以得到多个相同的对象

这里不得不谈到深克隆和浅克隆的概念了。

浅克隆

package com.designpatten.prototype.demo1;

import java.io.*;

public class Student implements Cloneable,Serializable{
    private String username;
    private String password;
    private Address address;

//    浅拷贝
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();//这个应该是浅拷贝,先试试
    }


    @Override
    public String toString() {
        return "Student{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", address=" + address +
                '}';
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Address getAddress() {
        return address;
    }

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

package com.designpatten.prototype.demo1;

import java.io.Serializable;

//学生类里面的地址信息
public class Address implements Cloneable, Serializable {
    private String province;
    private String city;
    private String country;

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

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

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

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

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

package com.designpatten.prototype.demo1;

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student = new Student();
        student.setAddress(new Address());
        student.setUsername("张三");
        student.setPassword("123123");
        Student student1 = (Student) student.clone();
        System.out.println(student.hashCode());
        System.out.println(student1.hashCode());
        //这里就体现出来了,对象中的引用类型只是复制了指针,并没有真正的拷贝,所以这个是浅拷贝
        System.out.println(student.getAddress().hashCode());
        System.out.println(student1.getAddress().hashCode());

        //这里再来一个深拷贝,用序列化的方式A

    }
}

运行结果
在这里插入图片描述
这里可以很明显的看出来,通过克隆方法获得的对象,那个对象是一个内容和原对象相同的另一个对象,但是对象中使用到的引用类型并不会拷贝一份,而只是拷贝了一份引用,这个就是浅拷贝

深拷贝

package com.designpatten.prototype.demo1;

import java.io.Serializable;

//学生类里面的地址信息
public class Address implements Cloneable, Serializable {
    private String province;
    private String city;
    private String country;

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

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

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

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

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}

package com.designpatten.prototype.demo1;

import java.io.*;

public class Student implements Cloneable,Serializable{
    private String username;
    private String password;
    private Address address;

    //深拷贝


    @Override
    protected Object clone() throws CloneNotSupportedException {
        ByteArrayOutputStream baos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bios = null;
        ObjectInputStream ois = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(this);      //将这个对象以对象流的方式写出
            //然后再创建一个输入流,读取新的,最后返回
            bios = new ByteArrayInputStream(baos.toByteArray());
            ois = new ObjectInputStream(bios);
            return ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (baos != null){
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    public String toString() {
        return "Student{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", address=" + address +
                '}';
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Address getAddress() {
        return address;
    }

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

package com.designpatten.prototype.demo1;

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student = new Student();
        student.setAddress(new Address());
        student.setUsername("张三");
        student.setPassword("123123");
        Student student1 = (Student) student.clone();
        System.out.println("student对象的hashCode");
        System.out.println(student.hashCode());
        System.out.println(student1.hashCode());
        //这里就体现出来了,对象中的引用类型只是复制了指针,并没有真正的拷贝,所以这个是浅拷贝
        System.out.println("student对象中的address的hashCode");
        System.out.println(student.getAddress().hashCode());
        System.out.println(student1.getAddress().hashCode());

        //这里再来一个深拷贝,用序列化的方式A

    }
}

运行结果
在这里插入图片描述
这里使用对象流的方式进行拷贝,最后clone出来的对象,无论是对象本身还是它内部的引用类型,都被克隆了一份,这个就是深拷贝

原型模式的优点

1.当创建新的对象实例较为复杂的时候,使用原型模式可以简化对象的创建过程,通过复制一个已有的实例可以提高新实例的创建效率
2.扩展性较好,由于再原型模式中提供了抽象原型类,在客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统没有任何影响
3.原型模式提供了简化的创建结构,工厂方法模式需要有一个与产品类等级结构相同的工厂等级结构,而原型模式就不需要这样,原型模式中产品的复制时通过封装在原型类中的克隆方法实现的
4.可以使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用

原型模式的缺点

1.需要为每一个类配备一个克隆方法,而且该克隆方法位于一个类的内部,当对已有的类进行改造时需要修改源代码,违背了开闭原则

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值