原型设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。

在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 !

目录

1.简介 2.什么是原型设计模式 3.解决问题 4.何时使用原型设计模式 5. JDK中的原型模式 6.下载源代码

1.简介

在面向对象编程中,您需要使用对象。 对象彼此交互以完成工作。 但是有时候,创建沉重的对象可能会变得很昂贵,并且如果您的应用程序需要太多此类对象(包含几乎相似的属性),则可能会带来一些性能问题。

让我们考虑一个应用程序需要一些访问控制的场景。 用户可以根据提供给他们的访问权限来使用应用程序的功能。 例如,有些用户有权访问由应用程序生成的报告,而有些则不能。 他们中有些甚至可以修改报告,而有些只能读取报告。 一些用户还具有添加或什至删除其他用户的管理权限。

每个用户对象都有一个访问控制对象,用于提供或限制应用程序的控件。 此访问控制对象是一个笨重的对象,其创建非常昂贵,因为它需要从某些外部资源(例如数据库或某些属性文件等)中获取数据。

我们也不能与同一级别的用户共享同一访问控制对象,因为管理员可以在运行时更改权限,并且同一级别的其他用户可以具有不同的访问控制。 一个用户对象应具有一个访问控制对象。

我们可以使用原型设计模式来解决此问题,方法是一次在所有级别上创建访问控制对象,然后在需要时向用户提供该对象的副本。 在这种情况下,从外部资源获取数据仅发生一次。 下次,通过复制现有对象来创建访问控制对象。 每次发送请求时,都不会从头开始创建访问控制对象。 这种方法肯定会减少对象创建时间。

在深入探讨解决方案之前,请让我们进一步了解原型设计模式。

2.什么是原型设计模式

原型设计模式用于指定要使用原型实例创建的对象的种类,并通过复制此原型来创建新对象。

其概念是复制现有对象,而不是从头开始创建新实例,这可能包括昂贵的操作。 现有对象充当原型,并包含对象的状态。 仅在需要时,新复制的对象才能更改相同的属性。 这种方法节省了昂贵的资源和时间,尤其是在对象创建很繁重的过程中。

在Java中,有某些方法可以复制对象以创建一个新对象。 实现此目的的一种方法是使用Cloneable接口。 Java提供了clone方法,该方法从Object类继承Object 。 您需要实现Cloneable接口,并根据需要覆盖此clone方法。

class_diagram_1

图1

原型

  • 声明一个用于克隆自身的接口。

具体原型

  • 实现克隆自身的操作。

客户

  • 通过要求原型克隆自己来创建新对象。

原型使您可以通过向客户端注册原型实例来将新的具体产品类合并到系统中。

3.解决问题

在此解决方案中,我们将使用克隆方法来解决上述问题。

package com.javacodegeeks.patterns.prototypepattern;public interface Prototype extends Cloneable {public AccessControl clone() throws CloneNotSupportedException;}

上面的接口扩展了Cloneable接口,并包含方法clone 。 该接口由要创建原型对象的类实现。

package com.javacodegeeks.patterns.prototypepattern;public class AccessControl implements Prototype{private final String controlLevel;private String access;public AccessControl(String controlLevel,String access){this.controlLevel = controlLevel;this.access = access;}@Overridepublic AccessControl clone(){try {return (AccessControl) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return null;}public String getControlLevel(){return controlLevel;}public String getAccess() {return access;}public void setAccess(String access) {this.access = access;}}

AccessControl类实现Prototype接口并覆盖clone方法。 该方法调用超类的clone方法,并将对象向下转换为AccessControl类型后返回该对象。 clone方法将引发CloneNotSupportedException ,该方法本身会捕获该异常。

该类还包含两个属性; controlLevel用于指定此对象包含的控制级别。 级别取决于要使用它的用户类型,例如USER,ADMIN,MANAGER等。

另一个属性是access ; 它包含用户的访问权限。 请注意,为简单起见,我们将访问权限用作String类型属性。 这可以是Map类型,可以包含分配给用户的长访问权限的键值对。

package com.javacodegeeks.patterns.prototypepattern;public class User {private String userName;private String level;private AccessControl accessControl;public User(String userName,String level, AccessControl accessControl){this.userName = userName;this.level = level;this.accessControl = accessControl;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getLevel() {return level;}public void setLevel(String level) {this.level = level;}public AccessControl getAccessControl() {return accessControl;}public void setAccessControl(AccessControl accessControl) {this.accessControl = accessControl;}@Overridepublic String toString(){return "Name: "+userName+", Level: "+level+", Access Control Level:"+accessControl.getControlLevel()+", Access: "+accessControl.getAccess();}}

User类具有userNamelevel和对分配给它的AccessControl的引用。

我们使用了一个AccessControlProvider类,该类预先创建和存储可能的AccessControl对象。 当有对AccessControl对象的请求时,它将返回一个通过复制存储的原型创建的新对象。

package com.javacodegeeks.patterns.prototypepattern;import java.util.HashMap;
import java.util.Map;public class AccessControlProvider {private static Map<String, AccessControl>map = new HashMap<String, AccessControl>();static{System.out.println("Fetching data from external resources and creating access control objects...");map.put("USER", new AccessControl("USER","DO_WORK"));map.put("ADMIN", new AccessControl("ADMIN","ADD/REMOVE USERS"));map.put("MANAGER", new AccessControl("MANAGER","GENERATE/READ REPORTS"));map.put("VP", new AccessControl("VP","MODIFY REPORTS"));}public static AccessControl getAccessControlObject(String controlLevel){AccessControl ac = null;ac = map.get(controlLevel);if(ac!=null){return ac.clone();}return null;}
}

getAccessControlObject方法根据传递给它的controlLevel获取存储的原型对象,并将新创建的克隆对象返回到客户端代码。

现在,让我们测试代码。

package com.javacodegeeks.patterns.prototypepattern;public class TestPrototypePattern {public static void main(String[] args) {AccessControl userAccessControl = AccessControlProvider.getAccessControlObject("USER");User user = new User("User A", "USER Level", userAccessControl);System.out.println("************************************");System.out.println(user);userAccessControl = AccessControlProvider.getAccessControlObject("USER");user = new User("User B", "USER Level", userAccessControl);System.out.println("Changing access control of: "+user.getUserName());user.getAccessControl().setAccess("READ REPORTS");System.out.println(user);System.out.println("************************************");AccessControl managerAccessControl = AccessControlProvider.getAccessControlObject("MANAGER");user = new User("User C", "MANAGER Level", managerAccessControl);System.out.println(user);}
}

上面的代码将产生以下输出:

Fetching data from external resources and creating access control objects...
************************************
Name: User A, Level: USER Level, Access Control Level:USER, Access: DO_WORK
Changing access of: User B
Name: User B, Level: USER Level, Access Control Level:USER, Access: READ REPORTS
************************************
Name: User C, Level: MANAGER Level, Access Control Level:MANAGER, Access: GENERATE/READ REPORTS

在上面的代码中,我们在USER级别创建了一个AccessControl对象,并将其分配给UserA。然后,又将另一个AccessControl对象分配给User B,但是这次我们更改了User B的访问权限。最后,MANAGER用户C的级别访问控制。

getAccessControlObject用于获取AccessControl对象的新副本,当我们更改用户B的访问权限时,可以清楚地看到这一点,而对于用户A的访问权限没有更改(只需再次打印用户A对象)。 这确认clone方法工作正常,因为它返回对象的新副本,而不是指向同一对象的引用。

4.何时使用原型设计模式

当系统应独立于其产品的创建,组成和表示方式时,请使用原型模式。 和

  • 在运行时指定要实例化的类时,例如,通过动态加载; 要么
  • 为了避免建立与产品的类层次结构平行的工厂的类层次结构; 要么
  • 当一个类的实例只能具有几种不同的状态组合之一时。 安装相应数量的原型并克隆它们,而不是每次都以适当的状态手动实例化类,可能会更方便。

5. JDK中的原型模式

  • java.lang.Object#clone()
  • java.lang.Cloneable

6.下载源代码

这是关于原型设计模式的课程。 您可以在此处下载源代码: PrototypePattern-Project

翻译自: https://www.javacodegeeks.com/2015/09/prototype-design-pattern.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/357025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【TypeScript系列教程14】Array数组对象的常见的方法

目录 TypeScript Array(数组) concat() every() filter() forEach() join() lastIndexOf() map() pop() push(

DELPHI跨平台的临界替代者

在WINDOWS里面使用临界来保护多线程需要访问的共享对象&#xff0c;现在&#xff0c;DELPHI有了新的跨平台临界保护者--System.TMonitor 代码演示如下&#xff1a; FConnections : TObjectDictionary<TIdTCPConnection,TDSTCPChannel>.Create; 。。。 procedure TCMServe…

laravel 控制器中使用中间件_在 Laravel 中使用 Slack 进行异常通知

php中文网最新课程每日17点准时技术干货分享异常处理是软件开发过程中无法逃避的问题。对于一套设计良好代码高效的程序&#xff0c;出现异常的可能性会比较低&#xff0c;但这并不意味着不会出现异常,有些异常甚至会引起严重的后果&#xff0c;所以如何及时的发现程序中的异常…

【TypeScript系列教程15】TypeScript 元组

我们知道数组中元素的数据类型都是相同的,如果存储的元素数据类型不同,则需要使用元组。 元组中允许存储不同类型的元素,元组可以作为参数传递给函数。 创建元组的语法格式如下: var tuple_name = [value1,value2,value3,…value n] 声明一个元组并初始化: var mytup…

[转]ListView学习笔记(一)——缓存机制

要想优化ListView首先要了解它的工作原理&#xff0c;列表的显示需要三个元素&#xff1a;ListView、Adapter、显示的数据&#xff1b; 这里的Adapter就是用到了适配器模式&#xff0c;不管传入的是什么View在ListView中都能显示出来。 下面简单说下上图的原理&#xff1a; 1、…

jax-rs jax-ws_Tomcat上具有JAX-WS的Web服务

jax-rs jax-ws让我们假设一家企业正在一个集中式系统中维护用户身份验证详细信息。 我们需要创建一个AuthenticationService&#xff0c;它将获取凭据&#xff0c;对其进行验证并返回状态。 其余的应用程序将使用AuthenticationService对用户进行身份验证。 创建Authentication…

golang反编译_【Golang】脱胎换骨的defer(一)

Go语言的defer是一个很方便的机制&#xff0c;能够把某些函数调用推迟到当前函数返回前才实际执行。我们可以很方便的用defer关闭一个打开的文件、释放一个Redis连接&#xff0c;或者解锁一个Mutex。而且Go语言在设计上保证&#xff0c;即使发生panic&#xff0c;所有的defer调…

【TypeScript系列教程16】TypeScript 联合类型

TypeScript 联合类型 联合类型(Union Types)可以通过管道 (|) 将变量设置多种类型,赋值时可以根据设置的类型来赋值。 注意:只能赋值指定的类型,如果赋值其它类型就会报错。 创建联合类型的语法格式如下 Type1|Type2|Type3 实例 声明一个联合类型: TypeScript var …

HTML 4.01 规定了三种文档类型

HTML 4.01 规定了三种文档类型&#xff1a;Strict、Transitional 以及 Frameset。 严格的——该 DTD 包含所有 HTML 元素和属性&#xff0c;但不包括展示性的和弃用的元素&#xff08;比如 font&#xff09;。不允许框架集&#xff08;Framesets&#xff09;。 <!DOCTYPE HT…

cad填充图案乱理石_CAD软件中如何自定义CAD填充图案?

在使用浩辰CAD软件绘制完成图纸后&#xff0c;发现自己绘制的CAD图纸没有做好区域分割&#xff0c;显得特别乱。这个时候该怎么办呢&#xff1f;快试试CAD填充图案吧&#xff01;接下来就由小编来给大家介绍一下浩辰CAD软件中自定义CAD填充图案的操作教程吧&#xff01;浩辰CAD…

单例设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中&#xff0c;您将深入研究大量的设计模式&#xff0c;并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因&#xff0c;并了解何时以及如何应用模式中的每一个。 在这里查看 &#xff01; 目录 …

Vue.js 组件编码规范

提供一种统一的编码规范来编写 Vue.js 代码。这使得代码具有如下的特性&#xff1a;* 其它开发者或是团队成员更容易阅读和理解。 * IDEs 更容易理解代码&#xff0c;从而提供高亮、格式化等辅助功能 * 更容易使用现有的工具 * 更容易实现缓存以及代码包的分拆基于模块开发始终…

centos图形化桌面的文件在哪_CentOS 安装图形桌面

1.显示系统已经安装的组件&#xff0c;和可以安装的组件:#yum grouplist|grep -i "x window"2.如果系统安装之初采用最小化安装&#xff0c;没有安装xwindow&#xff0c;那么先安装&#xff1a;#yum groupinstall "X Window System"3.安装GNOME桌面环境yum…

java高级架构师进阶路线,年薪百万的架构师都是按照这个路线学习的

一个合格的架构师,在接到这些产品,业务需求的时候,一定要能够全面的思考,给出除了业务需求外的系统需求,并要求自己或其他同学要去设计和实现这些系统需求。 所以你需要掌握这些知识点 目录 1.基本功 七大软件设计原则 设计模式 2.架构师审美观 spring源码分析

每天一个linux命令(53)--ps命令

要毁掉一天&#xff0c;从早上开始。 Linux中的ps命令是 process status 的缩写。ps 命令用来列出系统中当前运行的那些进程。ps 命令列出的是当前那些进程的快照&#xff0c;就是执行ps 命令的那个时刻的那些进程&#xff0c;如果想要动态的显示进程信息&#xff0c;就可以使用…

ansi编码转换_8b/1b编码是个什么东东

使用串行比并行总线可以节省更多的布线空间&#xff0c;芯片、电缆等的尺寸可以做得更小&#xff0c;同时传输速率更高。但是&#xff0c;在很多数字系统如CPU、DSP、FPGA等内部&#xff0c;进行数据处理的最小单位都是Byte&#xff0c;即8个bit&#xff0c;如何把一个或多个By…

格拉布斯准则异常数据_异常处理准则和最佳实践

格拉布斯准则异常数据让我们回顾一些基本的异常设计准则&#xff0c;这些准则从“对象设计&#xff1a;角色&#xff0c;职责和协作”中进行了总结&#xff08;Rebecca Wirfs-Brock和Alan McKean&#xff0c;Addison-Wesley&#xff0c;2003年&#xff09;。 不要尝试处理编码错…

使用CSDN云服务搭建一个WordPress 个人站点(详细教程)

目录 前言 站点效果图 搭建服务的一些准备工作 第一步。进入到云服务我的账号模块&#xff0c;创建一个项目&#xff0c; 第二步&#xff0c;先免费领取一台云主机&#xff0c; 第三步&#xff0c;进入云主机控制台 搭建站点操作步骤 第一步&#xff0c;登录云主机 第二…

echarts 卡_图表太丑怎么破,ECharts神器带你飞!

一、前言在本专栏或文集中&#xff0c;我曾多次使用ECharts绘制图表、进行可视化&#xff0c;也渐渐积累了30多个实例&#xff0c;本文对此前用过的所有图表和代码进行整理并分享&#xff0c;以给想绘制精美图表的人一点绵薄的帮助。其中全部实例已上传ECharts3官网的个人主页&…

Apache Lucene基础教程

课程大纲 Apache Lucene是一个免费/开源信息检索软件库&#xff0c;它提供基于Java的索引和搜索技术&#xff0c;以及拼写检查&#xff0c;命中突出显示和高级分析/令牌化功能。 Lucene是完全用Java编写的高性能&#xff0c;功能齐全的文本搜索引擎库。 它是一项适用于几乎所有…