【设计模式】快速理解原型模式,及其在源码中的应用

简介: 在正常的开发过程中,百分之99的对象实例都是通过new进行创建的,但是在实际的场景中,还是存在一些不通过new生成对象实例的应用场景。比如:需要生成大量类似的对象实例时,如果都通过new去创建,性能并不好。又比如:通过很复杂的方式生成了一个对象,现在要再创建出一个类似的对象出来。上面的两种应用场景都可以通过“拷贝”这个动作来实现,这种根据一个已有的原型对象,拷贝生成新的对象的方式,就是设计模式中的原型模式(prototype)。在Java中,可以通过Cloneable接口和clone方法很好地实现原型模式。

(一)什么是原型模式


在正常的开发过程中,百分之99的对象实例都是通过new进行创建的,但是在实际的场景中,还是存在一些不通过new生成对象实例的应用场景。


比如:需要生成大量类似的对象实例时,如果都通过new去创建,性能并不好。

又比如:通过很复杂的方式生成了一个对象,现在要再创建出一个类似的对象出来。


上面的两种应用场景都可以通过“拷贝”这个动作来实现,这种根据一个已有的原型对象,拷贝生成新的对象的方式,就是设计模式中的原型模式(prototype)。

在Java中,可以通过Cloneable接口和clone方法很好地实现原型模式。


(二)原型模式的简单例子


首先通过一个简单的例子让大家快速了解原型模式。


过年的时候公司给每个人发了一份邮件,这个邮件里除了署名和入职年份不一样以外,其他的内容都是相同的。比如:张三,这是你入职的第一年,祝你新年快乐XXXXX;李四,这是你入职的第二年,祝你新年快乐XXXXX。


这里的每一份邮件都可以理解为一个对象,而所有的对象实例都是相似的对象实例,因此就可以实用原型模式来拷贝生成这些重复的对象。


首先创建一个邮件对象,需要实现Cloneable接口:


publicclassMailimplementsCloneable{
privateStringname;
privateStringcontent;
privateIntegeryears;
Mail(Stringname,Stringcontent,Integeryears){
this.name=name;
this.content=content;
this.years=years;
System.out.println("对象创建成功");
    }
privatevoidshowMail(){
System.out.println(name+",这是你入职的第"+years+"年,"+content);
    }
@OverrideprotectedObjectclone() throwsCloneNotSupportedException {
System.out.println("拷贝成功");
returnsuper.clone();
    }
publicvoidsetContent(Stringcontent) {
this.content=content;
    }
publicvoidsetName(Stringname) {
this.name=name;
    }
publicvoidsetYears(Integeryears) {
this.years=years;
    }
}

接下来在使用的时候先通过new创建一个基础对象实例,其他的均通过clone进行拷贝:

publicstaticvoidmain(String[] args) throwsCloneNotSupportedException {
Mailmail=newMail("张三", "祝你新年快乐XXXXXX", 1);
mail.showMail();
MailcloneMail= (Mail) mail.clone();
cloneMail.setName("李四");
cloneMail.setYears(2);
mail.showMail();
}

这样一个简单的原型模式就实现了。


(三)基于管理器的原型模式


上面的例子可以增加对原型模式的理解,在实际开发中,更常用的是使用一个管理器去管理原型对象,可以在管理器类中通过一个HashMap保存原型对象。以水果店为例子。

首先定义了一个接口叫做Fruit,里面有两个方法:,shape方法用于展示水果的外观,createFruit方法用于通过克隆创建原型对象实例。


publicinterfaceFruitextendsCloneable{
voidshape();
ObjectcreateFruit() throwsException;
}

接着定义管理器,管理器由HashMap进行管理,提供注册和创建实例的功能:

publicclassFruitManager {
privateHashMap<String,Fruit>managerMap=newHashMap<>();
publicvoidregister(Stringname,Fruitfruit){
managerMap.put(name,fruit);
    }
publicFruitcreate(Stringname) throwsException{
Fruitfruit=managerMap.get(name);
return (Fruit) fruit.createFruit();
    }
}

下一步就是定义两个具体的对象,需要注意的是createFruit()方法使用了clone()进行拷贝:

publicclassAppleimplementsFruit{
@Overridepublicvoidshape() {
System.out.println("苹果是红色的圆形水果");
    }
@OverridepublicObjectcreateFruit() throwsException {
returnsuper.clone();
    }
}
publicclassOrangeimplementsFruit{
@Overridepublicvoidshape() {
System.out.println("橘子是黄色的圆形水果");
    }
@OverridepublicObjectcreateFruit() throwsException{
returnsuper.clone();
    }
}

最后写一个测试方法:

publicstaticvoidmain(String[] args) throwsException {
FruitManagermanager=newFruitManager();
//注册到管理器中manager.register("apple",newApple());
manager.register("orange",newOrange());
//通过create方法不断拷贝新的对象Fruitapple=manager.create("apple");
apple.shape();
Fruitorange=manager.create("orange");
orange.shape();
}

(四)原型模式在源码中的应用


其实在很多地方都用到了原型模式,比如最常用的ArrayList,同样定义了clone方法供调用者进行拷贝。


网络异常,图片无法展示
|


抛去Cloneable相关的接口,一些对象之间的复制操作也是原型模式的实践,比如Spring里BeanUtils.copyProperties()这个方法,同样实现了根据一个已有的原型对象,拷贝生成新的对象。


网络异常,图片无法展示
|

(五)总结


本章内容主要通过两个例子讲解了原型模式的概念以及应用,我是鱼仔,我们下期再见!



相关文章
|
2天前
|
设计模式 安全 数据库连接
后端开发中的设计模式应用
在软件开发的浩瀚海洋中,设计模式如同灯塔,为后端开发者指引方向。它们不仅仅是代码的模板,更是解决复杂问题的智慧结晶。本文将深入探讨几种常见的设计模式,包括单例模式、工厂模式和观察者模式,并揭示它们在实际应用中如何提升代码的可维护性、扩展性和重用性。通过实例分析,我们将一窥这些模式如何在后端开发中大放异彩,助力构建高效、灵活的软件系统。
|
3天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
3天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑】设计模式——原型模式
对比原型模式和传统方式的实现思路、代码方案、优缺点,阐述原型模式的使用场景,以及深拷贝、浅拷贝等相关概念,并扩展原型模式在Spring源码中的应用。
【Java笔记+踩坑】设计模式——原型模式
|
4天前
|
设计模式 数据库连接 PHP
PHP中的设计模式应用与最佳实践
在本文中,我们将探讨PHP设计模式的应用和最佳实践。通过深入分析,揭示如何在实际项目中有效利用设计模式来优化代码结构、提升系统灵活性和维护性,并分享一些常见设计模式的实际应用案例。无论你是PHP初学者还是经验丰富的开发者,这篇文章都会对你有所帮助。
|
22天前
|
设计模式 算法 开发者
深入理解工厂模式与策略模式:设计模式的灵活应用
深入理解工厂模式与策略模式:设计模式的灵活应用
|
30天前
|
设计模式
设计模式:从理论到实际应用
【8月更文挑战第18天】设计模式是软件工程中解决特定问题的有效方案,提升代码质量并促进团队协作。本文从理论出发,探讨设计模式在实际项目中的应用。设计模式分为创建型、结构型和行为型,遵循如开闭原则等设计原则。通过工厂模式创建不同类型的电子签章,观察者模式实现在状态变更时的通知机制,以及建造者模式灵活组装复杂对象。以虚拟运营商平台为例,采用责任链模式优化审批流程,展示设计模式的实际价值。
|
17天前
|
前端开发 C# 设计模式
“深度剖析WPF开发中的设计模式应用:以MVVM为核心,手把手教你重构代码结构,实现软件工程的最佳实践与高效协作”
【8月更文挑战第31天】设计模式是在软件工程中解决常见问题的成熟方案。在WPF开发中,合理应用如MVC、MVVM及工厂模式等能显著提升代码质量和可维护性。本文通过具体案例,详细解析了这些模式的实际应用,特别是MVVM模式如何通过分离UI逻辑与业务逻辑,实现视图与模型的松耦合,从而优化代码结构并提高开发效率。通过示例代码展示了从模型定义、视图模型管理到视图展示的全过程,帮助读者更好地理解并应用这些模式。
30 0
|
17天前
|
设计模式 安全 数据库连接
|
18天前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
13 0
|
27天前
|
设计模式 SQL 缓存
Java编程中的设计模式:单例模式的深入理解与应用
【8月更文挑战第22天】 在Java的世界里,设计模式是构建可维护、可扩展和灵活的软件系统的基石。本文将深入浅出地探讨单例模式这一经典设计模式,揭示其背后的哲学思想,并通过实例演示如何在Java项目中有效运用。无论你是初学者还是资深开发者,这篇文章都将为你打开一扇洞悉软件设计深层逻辑的大门。
26 0