Java设计模式之原型模式(创建型模式)-阿里云开发者社区

开发者社区> 顾漫漫长路> 正文

Java设计模式之原型模式(创建型模式)

简介: 定义:原型模式就是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。 ​ 在应用程序中,有些对象比较复杂,其创建过程过于复杂,而且我们又需要频繁的利用该对象,如果这个时候我们按照常规思维new该对象,那么务必会造成资源浪费,这个时候我们就希望可以利用一个已有的对象来不断对他进行复制就好了,这就是编程中的“克隆”。
+关注继续查看

定义:原型模式就是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。

在应用程序中,有些对象比较复杂,其创建过程过于复杂,而且我们又需要频繁的利用该对象,如果这个时候我们按照常规思维new该对象,那么务必会造成资源浪费,这个时候我们就希望可以利用一个已有的对象来不断对他进行复制就好了,这就是编程中的“克隆”。原型模式直接操作底层二进制流,在创建复杂对象是效率提升明显。

UML类图:

浅克隆与深克隆:

浅克隆:当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制。

深克隆:除了对象本身被复制外,对象所包含的所有成员变量也将被复制。

浅克隆:

public class Person implements Cloneable {

    private String name;

    private boolean gender;

    private Interest interest;

 

    public Person(String name, boolean gender, Interest interest) {

        this.name = name;

        this.gender = gender;

        this.interest = interest;

    }

 

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public boolean isGender() {

        return gender;

    }

    public void setGender(boolean gender) {

        this.gender = gender;

    }

    public Interest getInterest() {

        return interest;

    }

    public void setInterest(Interest interest) {

        this.interest = interest;

    }

 

    @Override

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", gender=" + gender +

                ", interest=" + interest +

                '}';

    }

 

    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone();

    }

 

    public static void main(String[] args) throws CloneNotSupportedException {

        Interest interest = new Interest("摄影");

        Person gg = new Person("gg",false,interest);

        System.out.println(gg);

        Person dxy = (Person)gg.clone();

        dxy.setName("dxy");

        dxy.setGender(true);

        dxy.interest.setName("咖啡");

        System.out.println(dxy);

        System.out.println(gg);

    }

}

class Interest{

    private String name;

 

    public Interest(String name) {

        this.name = name;

    }

 

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    public String toString() {

        return "Interest{" +

                "name='" + name + '\'' +

                '}';

    }

}

运行结果:


Person{name='gg', gender=false, interest=Interest{name='摄影'}}

Person{name='dxy', gender=true, interest=Interest{name='咖啡'}}

Person{name='gg', gender=false, interest=Interest{name='咖啡'}}

浅克隆对于引用类型,只克隆了引用,因此两个对象的interest公共同一个内存地址,一个对象变化,会引起另一个对象响应的变化。

深克隆:

    public class Person implements Cloneable {

    private String name;

    private boolean gender;

    private Interest interest;

 

    public Person(String name, boolean gender, Interest interest) {

        this.name = name;

        this.gender = gender;

        this.interest = interest;

    }

 

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public boolean isGender() {

        return gender;

    }

    public void setGender(boolean gender) {

        this.gender = gender;

    }

    public Interest getInterest() {

        return interest;

    }

    public void setInterest(Interest interest) {

        this.interest = interest;

    }

 

    @Override

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", gender=" + gender +

                ", interest=" + interest +

                '}';

    }

 

    @Override

    protected Object clone() throws CloneNotSupportedException {

        Object obj = super.clone();  //直接调用object对象的clone()方法!

        //添加如下代码实现深复制(deep Clone)

        Person person = (Person) obj;

        person.interest = (Interest)this.interest.clone(); //把属性也进行克隆!

        return obj;

    }

 

    public static void main(String[] args) throws CloneNotSupportedException {

        Interest interest = new Interest("摄影");

        Person gg = new Person("gg",false,interest);

        System.out.println(gg);

        Person dxy = (Person)gg.clone();

        dxy.setName("dxy");

        dxy.setGender(true);

        dxy.interest.setName("咖啡");

        System.out.println(dxy);

        System.out.println(gg);

    }

    }

    class Interest implements Cloneable {

    private String name;

 

    public Interest(String name) {

        this.name = name;

    }

 

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    protected Object clone() throws CloneNotSupportedException {

        return super.clone();

    }

 

    @Override

    public String toString() {

        return "Interest{" +

                "name='" + name + '\'' +

                '}';

    }
    }

运行结果:


Person{name='gg', gender=false, interest=Interest{name='摄影'}}

Person{name='dxy', gender=true, interest=Interest{name='咖啡'}}

Person{name='gg', gender=false, interest=Interest{name='摄影'}}

通过对引用类型值Interest添加clone方法,并且对Person对象的clone方法改造,实现深克隆。

此外还可以通过序列化和反序列化的方式实现深复制。


    public class Person implements Serializable {

    private String name;

    private boolean gender;

    private Interest interest;

 

    public Person(String name, boolean gender, Interest interest) {

        this.name = name;

        this.gender = gender;

        this.interest = interest;

    }

 

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public boolean isGender() {

        return gender;

    }

    public void setGender(boolean gender) {

        this.gender = gender;

    }

    public Interest getInterest() {

        return interest;

    }

    public void setInterest(Interest interest) {

        this.interest = interest;

    }

 

    @Override

    public String toString() {

        return "Person{" +

                "name='" + name + '\'' +

                ", gender=" + gender +

                ", interest=" + interest +

                '}';

    }

 

    public static void main(String[] args) throws CloneNotSupportedException,ClassNotFoundException,IOException {

        Interest interest = new Interest("摄影");

        Person gg = new Person("gg",false,interest);

        System.out.println(gg);

        //使用序列化和反序列化实现深复制

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(gg);

        byte[] bytes = bos.toByteArray();

 

        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

        ObjectInputStream ois = new ObjectInputStream(bis);

 

        Person dxy = (Person) ois.readObject();   //克隆好的对象!

        dxy.interest.setName("咖啡");

 

        System.out.println(dxy);

        System.out.println(gg);

    }

    }



    class Interest implements Serializable{

    private String name;

 

    public Interest(String name) {

        this.name = name;

    }

 

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

 

    @Override

    public String toString() {

        return "Interest{" +

                "name='" + name + '\'' +

                '}';

    }

}

运行结果:


Person{name='gg', gender=false, interest=Interest{name='摄影'}}

Person{name='gg', gender=false, interest=Interest{name='咖啡'}}

Person{name='gg', gender=false, interest=Interest{name='摄影'}}

优点:

当创建对象的实例较为复杂的时候,使用原型模式可以简化对象的创建过程。

直接操作二进制流,可以提高实例的创建效率。

缺点:

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

在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重签到引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。

此外clone对象时,不调用构造方法,无视构造方法的权限。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
深入理解设计模式!五大创建型模式的详细解析
本篇文章中介绍了设计模式中的五大创建型模式。包括工厂方法模式,抽象工厂模式,单例模式,建造者模式以及原型模式。通过对五种创建模式的基本介绍以及使用示例的分析,可以理解设计模式中创建型模式的使用方式和使用场景。
20 0
JavaScript创建对象(四)——组合使用构造函数和原型模式
在JavaScript创建对象(三)——原型模式中,我们阐述了原型模式存在的两个问题:一是没办法通过构造函数初始化对象属性,二是共享引用类型的数据导致数据错乱。
825 0
【设计模式】原型模式 ( 浅拷贝 | 深拷贝 | 原型与单例冲突 | 禁用 final )(一)
【设计模式】原型模式 ( 浅拷贝 | 深拷贝 | 原型与单例冲突 | 禁用 final )(一)
7 0
JavaScript创建对象(三)——原型模式
在JavaScript创建对象(二)——构造函数模式中提到,构造函数模式存在相同功能的函数定义多次的问题。本篇文章就来讨论一下该问题的解决方案——原型模式。
1044 0
8
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载