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

简介: 在正常的开发过程中,百分之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月前
|
设计模式 PHP
PHP中的设计模式:单一职责原则在软件开发中的应用
【10月更文挑战第8天】 在软件开发中,设计模式是解决常见问题的经验总结,而单一职责原则作为面向对象设计的基本原则之一,强调一个类应该只有一个引起变化的原因。本文将探讨单一职责原则在PHP中的应用,通过实际代码示例展示如何运用该原则来提高代码的可维护性和可扩展性。
36 1
|
4天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
4天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
4天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
|
1月前
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
32 2
|
1月前
|
设计模式 监控 算法
Python编程中的设计模式应用与实践感悟###
在Python这片广阔的编程疆域中,设计模式如同导航的灯塔,指引着开发者穿越复杂性的迷雾,构建出既高效又易于维护的代码结构。本文基于个人实践经验,深入探讨了几种核心设计模式在Python项目中的应用策略与实现细节,旨在为读者揭示这些模式背后的思想如何转化为提升软件质量的实际力量。通过具体案例分析,展现了设计模式在解决实际问题中的独特魅力,鼓励开发者在日常编码中积极采纳并灵活运用这些宝贵的经验总结。 ###
|
1月前
|
设计模式 开发者 Python
Python编程中的设计模式应用与实践感悟####
本文作为一篇技术性文章,旨在深入探讨Python编程中设计模式的应用价值与实践心得。在快速迭代的软件开发领域,设计模式如同导航灯塔,指引开发者构建高效、可维护的软件架构。本文将通过具体案例,展现设计模式如何在实际项目中解决复杂问题,提升代码质量,并分享个人在实践过程中的体会与感悟。 ####
|
1月前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
22 1
|
2月前
|
设计模式 PHP 开发者
PHP中的设计模式:桥接模式的解析与应用
在软件开发的浩瀚海洋中,设计模式如同灯塔一般,为开发者们指引方向。本文将深入探讨PHP中的一种重要设计模式——桥接模式。桥接模式巧妙地将抽象与实现分离,通过封装一个抽象的接口,使得实现和抽象可以独立变化。本文将阐述桥接模式的定义、结构、优缺点及其应用场景,并通过具体的PHP示例代码展示如何在实际项目中灵活运用这一设计模式。让我们一起走进桥接模式的世界,感受它的魅力所在。
|
2月前
|
设计模式 测试技术 持续交付
架构视角下的NHibernate:设计模式与企业级应用考量
【10月更文挑战第13天】随着软件开发向更复杂、更大规模的应用转变,数据访问层的设计变得尤为重要。NHibernate作为一个成熟的对象关系映射(ORM)框架,为企业级.NET应用程序提供了强大的支持。本文旨在为有一定经验的开发者提供一个全面的指南,介绍如何在架构层面有效地使用NHibernate,并结合领域驱动设计(DDD)原则来构建既强大又易于维护的数据层。
42 2