设计模式之原型模式详解

这篇具有很好参考价值的文章主要介绍了设计模式之原型模式详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在设计模式的系列文章中,我们前面已经写了工厂模式单列模式建造者模式,在针对创建型模式中,今天想跟大家分享的是原型模式,我觉的这种模式叫克隆模式会更佳恰当。原型模式的目的就是通过复制一个现有的对象来生成一个新的对象。

模式概述

原型模式

使用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的对象,原型模式是一种对象的创建型模式

工作原理

将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象克隆自己来实现创建的过程,通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址;通常,对克隆产生的对象进行的修改不会对原型对象造成任何影响,每一个克隆的对象都是相互独立的。

原型模式的结构

原型模式模式分为两种,一种是不带管理类的原型模式,另一种是带管理类的原型模式。

下面这种是不带管理类的原型模式:

 设计模式之原型模式详解,设计模式,tomcat,java

定义

原型模式包含了三个角色

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

需要注意的点:

在 Java 中 能够克隆的 Java类 务必得 实现 Cloneable 接口,表示这个 类 能够被 “复制”,至于这个 复制的效果 则与我们的实现有关,通常 clone()方法满足以下的条件:

  • 对任何的对象x,都有:x.clone()!=x 。换言之,克隆对象与元对象不是一个对象
  • 对任何的对象x,都有:x.clone().getClass==x.getClass(),换言之,克隆对象与元对象的类型一样
  • 对任何的对象x,如果 equals() 方法编写得当的话, 那么x.clone().equals(x)应该是成立的

在正式开始原型模式之前,我们先了解两个概念浅克隆和深克隆浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制

浅拷贝与深拷贝

A、浅拷贝

    被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。即浅拷贝只负责当前对象实例,对引用的对象不做拷贝。

设计模式之原型模式详解,设计模式,tomcat,java

B、深拷贝

    被拷贝对象的所有的变量都含有与原来对象相同的值,除了引用其他对象的变量。引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有被引用对象。即深拷贝把要拷贝的对象所引用的对象也都拷贝了一次。

    深拷贝要深入到多少层,是一个不确定的问题。在决定以深拷贝的方式拷贝一个对象的时候,必须决定对间接拷贝的对象是采取浅拷贝还是深拷贝还是继续采用深拷贝。因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。

设计模式之原型模式详解,设计模式,tomcat,java

我们通过一个实例来看一下具体的使用过程。

我们举一个大学里常见的例子,一个班里有一个学霸的话整个班级的作业就不用愁了,大家可以拿学霸的作业去复制嘛。

这个类是作业的抽象父类,定义了一些作业都要实现的方法,这里只实现了一个数学作业类,将来可以能有编程作业等。

package com.designpattern.prototype1;

public abstract class Homework implements Cloneable {
    public abstract Object clone();
    public abstract void show();
}

数学作业的类要实现自己的复制逻辑,因为数学作业和编程作业的抄袭的方法肯定是不一样的。

package com.designpattern.prototype1;

import java.util.Date;

public class MathHomework extends Homework{
    /**
     * 这里只是用一个日期类来表示一下深度复制
     */
    private Date A = new Date();
    private int a = 1;

    public void show() {
        System.out.println("Math clone");
    }

    /**
     * 实现自己的克隆方法
     */
    public Object clone(){

        MathHomework m = null;
        /**
         * 深度复制
         */
        m = (MathHomework) this.clone();
        m.A = (Date)this.getA().clone();

        return m;
    }

    public Date getA(){
        return A;
    }

}

客户端就可以使用学霸的作业抄袭了

package com.designpattern.prototype1;

public class Main {

    public static void main(String[] args){
        /**
         * 建立一个学霸,全班同学的作业就靠他了
         */
        MathHomework xueba = new MathHomework();
        /**
         * 学渣都是从学霸那复制来的
         */
        MathHomework xuezha = (MathHomework)xueba.clone();
        xuezha.show();
    }
}

那如果一个班里有两个学霸呢,那肯定班里的同学有的会超A同学的,有的会抄B同学的,这样的话系统里就必须要保留两个原型类,这时候使用我们的带有管理类的原型模式就比较方便了。

此时的结构图是这样的:

设计模式之原型模式详解,设计模式,tomcat,java

新增加的管理类:

package com.designpattern.prototype1;

import java.util.Map;

public class Manager {
    private static Manager manager;
    private Map prototypes = null;

    private Manager() {
        manager = new Manager();
    }

    //使用了简单工厂模式
    public static Manager getManager() {
        if (manager == null)
            manager = new Manager();
        return manager;
    }

    public void put(String name,Homework prototype){
        manager.put(name, prototype);
    }

    public Homework getPrototype(String name){
        if(prototypes.containsKey(name)){
            return (Homework) ((Homework)prototypes.get(name)).clone();
        }else{
            Homework homework = null;
            try{
                homework = (Homework)Class.forName(name).newInstance();
                put(name, homework);
            }catch(Exception e){
                e.printStackTrace();
            }

            return homework;
        }
    }

}
package com.designpattern.prototype1;

public class MainManager {

    public static void main(String[] args){
        /**
         * 建立一个学霸,全班同学的作业就靠他了
         */
        MathHomework xueba = new MathHomework();

        Manager.getManager().put("com.designpattern.prototype1.MathHomework", xueba);
        /**
         * 学渣都是从学霸那复制来的
         */
        MathHomework xuezha = (MathHomework) Manager.getManager().getPrototype("com.designpattern.prototype1.MathHomework");
        xuezha.show();
    }
}

简单形式和登记形式的原型模式各有其长处和短处,如果需要创建的原型对象数目较少 而且比较固定的话可以采取简单形式,如果创建的原型对象数目不固定的话建议采取第二种形式。

原型模式优缺点

优点:

  1. 原型模式对客户隐藏了具体的产品类
  2. 运行时刻增加和删除产品: 原型模式允许只通过客户注册原型实例就可以将一个新的具体产品类并入系统。
  3. 改变值以指定新对象: 高度动态的系统允许通过对象复合定义新的行为。如通过为一个对象变量指定值并且不定义新的类。通过实例化已有类并且将实例注册为客户对象的原型,就可以有效定义新类别的对象。客户可以将职责代理给原型,从而表现出新的行为。
  4. 改变结构以指定新对象:许多应用由部件和子部件来创建对象。
  5. 减少子类的构造,Prototype模式克隆一个原型而不是请求一个工厂方法去产生一个新的对象。
  6. 用类动态配置应用 一些运行时刻环境允许动态将类装载到应用中。
  7. 使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。
  8. 使用原型模式的另一个好处是简化对象的创建,使得创建对象很简单。

缺点:

    原型模式的主要缺陷是每一个抽象原型Prototype的子类都必须实现clone操作,实现clone函数可能会很困难。当所考虑的类已经存在时就难以新增clone操作,当内部包括一些不支持拷贝或有循环引用的对象时,实现克隆可能也会很困难的。

适用场景

  1. 资源优化场景。
  2. 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。
  3. 性能和安全要求的场景。
  4. 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
  5. 一个对象多个修改者的场景。
  6. 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
  7. 在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过 clone 的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与 Java 融为浑然一体,大家可以随手拿来使用。

注意事项:与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。 

设计模式之原型模式详解,设计模式,tomcat,java文章来源地址https://www.toymoban.com/news/detail-652297.html

到了这里,关于设计模式之原型模式详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java设计模式之原型模式

            原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。         这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大

    2024年02月10日
    浏览(31)
  • Java设计模式-原型模式(3)

         馆长准备了很多学习资料,其中包含 java方面,jvm调优,spring / spring boot /spring cloud ,微服务,分布式,前端,js书籍资料,视频资料,以及各类常用软件工具,破解工具 等资源。请关注“IT技术馆”公众号,进行关注,馆长会每天更新资源和更新技术文章等。请大家多

    2024年01月21日
    浏览(34)
  • 设计模式篇(Java):原型模式

    上一篇:设计模式篇(Java):工厂模式 需求示例—克隆羊 现在有一只羊tom,姓名为: tom, 年龄为:1,颜色为:白色,请编写程序创建和tom 羊属性完全相同的10只羊。 不使用设计模式(传统方式)实现: 分析: 优点是比较好理解,简单易操作。 在创建新的对象时,总是需要重

    2024年02月11日
    浏览(27)
  • Java设计模式之 - 原型模式

    原型模式是一种创建型设计模式,它允许我们通过克隆现有对象来创建新对象,而无需从头开始构建对象。 在该模式中,一个原型对象被克隆来生成新的对象,新对象的属性可以根据原型对象来设置,也可以进行修改。 原型模式主要解决的问题是对象的创建成本过高或者对

    2024年02月16日
    浏览(24)
  • Java原型设计模式

    Java原型模式(Prototype Pattern)是一种创建型设计模式,它允许通过复制现有对象来创建新的对象,而无需显式地指定它们的类。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个

    2024年02月13日
    浏览(30)
  • 《Java极简设计模式》第05章:原型模式(Prototype)

    作者:冰河 星球:http://m6z.cn/6aeFbs 博客:https://binghe.gitcode.host 文章汇总:https://binghe.gitcode.host/md/all/all.html 源码地址:https://github.com/binghe001/java-simple-design-patterns/tree/master/java-simple-design-prototype 沉淀,成长,突破,帮助他人,成就自我。 本章难度:★★☆☆☆ 本章重点:用

    2024年02月11日
    浏览(30)
  • Java设计模式之创建型-原型模式(UML类图+案例分析)

    目录 一、基础概念 二、UML类图 三、角色设计 四、案例分析  4.1、通用实现(浅克隆) 4.2、深克隆 五、总结 原型模式通过复制已有对象作为原型,通过复制该原型来返回一个新对象,而不是新建对象,说白了就是不断复制相同的对象罢了。 角色 描述 抽象原型类 规定了具

    2024年02月15日
    浏览(38)
  • 【java设计模式】创建型模式介绍(工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式)

    简介 本文介绍Java设计模式中创建型模式的五种 一、工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 工厂模式提供了一种将对象的实例化过程封装在工厂类中的方式。通过使用工

    2024年02月16日
    浏览(40)
  • [设计模式Java实现附plantuml源码~创建型] 对象的克隆~原型模式

    前言: 为什么之前写过Golang 版的设计模式,还在重新写 Java 版? 答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。 为什么类图要附上uml 因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那

    2024年01月23日
    浏览(29)
  • 【设计模式——学习笔记】23种设计模式——原型模式Prototype(原理讲解+应用场景介绍+案例介绍+Java代码实现)

    原型模式指用通过拷贝原型实例创建新的实例,新实例和原型实例的属性完全一致 原型模式是一种创建型设计模式 工作原理是通过调用原型实例的 clone() 方法来完成克隆,原型实例需要实现Cloneable接口,并重写 clone() 方法 需要为每个类开发一个克隆方法,这对全新的类来说

    2024年02月16日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包