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对象时,不调用构造方法,无视构造方法的权限。

相关文章
|
26天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
26天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
2月前
|
设计模式 架构师 Java
设计模式之 5 大创建型模式,万字长文深剖 ,近 30 张图解!
设计模式是写出优秀程序的保障,是让面向对象保持结构良好的秘诀,与架构能力与阅读源码的能力息息相关,本文深剖设计模式之 5 大创建型模式。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
设计模式之 5 大创建型模式,万字长文深剖 ,近 30 张图解!
|
2月前
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
|
2月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
48 4
|
3月前
|
设计模式 Java 程序员
[Java]23种设计模式
本文介绍了设计模式的概念及其七大原则,强调了设计模式在提高代码重用性、可读性、可扩展性和可靠性方面的作用。文章还简要概述了23种设计模式,并提供了进一步学习的资源链接。
67 0
[Java]23种设计模式
|
2月前
|
设计模式 JavaScript Java
Java设计模式:建造者模式详解
建造者模式是一种创建型设计模式,通过将复杂对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。本文详细介绍了建造者模式的原理、背景、应用场景及实际Demo,帮助读者更好地理解和应用这一模式。
|
3月前
|
设计模式 监控 算法
Java设计模式梳理:行为型模式(策略,观察者等)
本文详细介绍了Java设计模式中的行为型模式,包括策略模式、观察者模式、责任链模式、模板方法模式和状态模式。通过具体示例代码,深入浅出地讲解了每种模式的应用场景与实现方式。例如,策略模式通过定义一系列算法让客户端在运行时选择所需算法;观察者模式则让多个观察者对象同时监听某一个主题对象,实现松耦合的消息传递机制。此外,还探讨了这些模式与实际开发中的联系,帮助读者更好地理解和应用设计模式,提升代码质量。
Java设计模式梳理:行为型模式(策略,观察者等)
|
4月前
|
存储 设计模式 安全
Java设计模式-备忘录模式(23)
Java设计模式-备忘录模式(23)
|
4月前
|
设计模式 存储 算法
Java设计模式-命令模式(16)
Java设计模式-命令模式(16)

热门文章

最新文章

  • 1
    设计模式转型:从传统同步到Python协程异步编程的实践与思考
    64
  • 2
    C++一分钟之-设计模式:工厂模式与抽象工厂
    54
  • 3
    《手把手教你》系列基础篇(九十四)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-下篇(详解教程)
    60
  • 4
    C++一分钟之-C++中的设计模式:单例模式
    79
  • 5
    《手把手教你》系列基础篇(九十三)-java+ selenium自动化测试-框架设计基础-POM设计模式实现-上篇(详解教程)
    47
  • 6
    《手把手教你》系列基础篇(九十二)-java+ selenium自动化测试-框架设计基础-POM设计模式简介(详解教程)
    80
  • 7
    Java面试题:结合设计模式与并发工具包实现高效缓存;多线程与内存管理优化实践;并发框架与设计模式在复杂系统中的应用
    70
  • 8
    Java面试题:设计模式在并发编程中的创新应用,Java内存管理与多线程工具类的综合应用,Java并发工具包与并发框架的创新应用
    54
  • 9
    Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
    63
  • 10
    Java面试题:请列举三种常用的设计模式,并分别给出在Java中的应用场景?请分析Java内存管理中的主要问题,并提出相应的优化策略?请简述Java多线程编程中的常见问题,并给出解决方案
    137