Android设计模式--原型模式

一,定义

原型模式就是用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象

也就是说用户从一个实例中复制出一个内部属性一致的对象,这个被复制的对象就是原型。

原型模式多用于创建复杂的或者构造耗时的实例,因为这种情况下复制一个已经存在的实例可使程序运行更高效。

二,使用场景

1,类初始化需要消耗非常多的资源

2,通过new产生一个对象需要非常繁琐的数据准备或访问权限

3,一个对象需要提供给其他对象访问,而且各个调用者都可能会修改其值时,可以使用原型模式拷贝多个对象供调用者使用,即保护性拷贝

注意:通过实现Cloneable接口的原型模式在调用clone函数构造实例时并不一定比通过new操作速度快,只有当通过new构造对象较为耗时时,通过clone方法才能获得效率上的提高。

三,通过Cloneable实现原型模式

假设有这样一个需求,用户通过网络请求获取到服务器上的用户信息,其他模块可以拿到用户信息,本地修改用户信息以供展示用,但是各个模块拿到的用户信息必须得是服务器上请求的原始的用户信息。

这种情况下我们就可以使用原型模式来实现。

首先新建我们的user类:实现clone方法,拷贝对象

/*** 用户信息 实现cloneable接口* */
public class User implements Cloneable {private String userName;private int age;private String address;public void setUserName(String userName) {this.userName = userName;}public void setAge(int age) {this.age = age;}public void setAddress(String address) {this.address = address;}public String getUserName() {return userName;}public int getAge() {return age;}public String getAddress() {return address;}@NonNull@Overrideprotected User clone() throws CloneNotSupportedException {User user = (User) super.clone();user.userName =this.userName;user.address =this.address;user.age =this.age;return user;}
}

然后创建缓存数据类,注意,返回的是User的clone对象:

public class UserDao {private User user;private UserDao(){}public static UserDao getInstance(){return UserDao.SingletonHolder.userDao;}private static class SingletonHolder{private static final UserDao userDao =new UserDao();}public void setUser(User user) {this.user = user;}public User getUser() {try {return user.clone();} catch (CloneNotSupportedException e) {throw new RuntimeException(e);}}
}

然后模拟服务器获取数据和不同模块间设置用户信息的操作:

public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);getUserFromNet();setUserAgeM1();setUserAgeM2();}/*** 模拟从服务器获取user数据存到本地* */public void getUserFromNet(){User user =new User();user.setUserName("袁震");user.setAge(20);user.setAddress("淄博");UserDao.getInstance().setUser(user);}/*** 模拟M1模块设置年龄* */public void setUserAgeM1(){User user =UserDao.getInstance().getUser();Log.d(TAG,"yz-----M1模块获得年龄:"+user.getAge());user.setAge(28);Log.d(TAG,"yz-----M1模块设置年龄:"+user.getAge());}/*** 模拟M2模块获得年龄* */public void setUserAgeM2(){User user =UserDao.getInstance().getUser();Log.d(TAG,"yz-----M2模块获得年龄:"+user.getAge());user.setAge(30);Log.d(TAG,"yz-----M2模块设置年龄:"+user.getAge());}}

最后输出结果:

四,通过其他方式实现原型模式

原型模式不一定必须通过实现cloneable接口来实现,因为有时候拷贝的效率并不一定比new的效率高。

在上述案例中,User类也可以这样实现:

/*** 用户信息 实现cloneable接口* */
public class User {private String userName;private int age;private String address;public void setUserName(String userName) {this.userName = userName;}public void setAge(int age) {this.age = age;}public void setAddress(String address) {this.address = address;}public String getUserName() {return userName;}public int getAge() {return age;}public String getAddress() {return address;}protected User clone(){User user = new User();user.userName =this.userName;user.address =this.address;user.age =this.age;return user;}
}

五,总结

原型模式本质上就是对象拷贝,与C++中的深拷贝,浅拷贝类似,不了解的可以查看文章Android JNI2--C++基础-CSDN博客

优点:原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好的体现其优点

缺点:直接在内存中拷贝,构造函数是不会执行的,实际开发时需要注意

参考文献:Android源码设计模式解析与实战第二版

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

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

相关文章

Python入门:一文详解Python列表(List)操作方法

文章目录 前言一、创建一个列表二、访问列表中的值三、更新列表四、删除列表元素六、Python列表截取七、Python列表操作的函数和方法关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②…

IntelliJ IDEA cmd和idea Terminal查看java版本不一致

参考:IntelliJ IDEA cmd和idea Terminal查看java版本不一致的解决方案 1、idea清缓存重启 没用 2、删除缓存文件 没试 3、修改环境变量的顺序 没试 4、重启电脑 麻烦,没试 5、项目配置jdk7 没试 按照这个url配置了一个遍 https://blog.csdn…

AIOT数字孪生智慧工地一体化管理平台源码

智慧工地app基于物联网和移动互联网技术,利用各类传感器及终端设备通过与云端服务器的实时数据交互,为施工现场的管理人员提供环境监测、劳务实名制管理、物料管理、巡检记录、设备管理等一系列优质高效的行业解决方案。 一、智能工地应用价值 智慧工地…

入选《人工智能领域内容榜》

2023-11-13 入选《人工智能领域内容榜》31 C# OpenCvSharp DNN HybridNets 同时处理车辆检测、可驾驶区域分割、车道线分割

并发编程产生的根本原因和C#怎么处理并发问题?

并发编程产生的根本原因和C#怎么处理并发问题? 前言 对于现在很多编程语言来说,多线程已经得到了很好的支持, 以至于我们写多线程程序简单,但是一旦遇到并发产生的问题就会各种尝试。 因为不是明白为什么会产生并发问题&#…

React Virtual DOM及Diff算法

JSX到底是什么 使用React就一定会写JSX,JSX到底是什么呢?它是一种JavaScript语法的扩展,React使用它来描述用户界面长成什么样子,虽然它看起来非常像HTML,但他确实是javaScript,在React代码执行之前&#…

Nginx 是如何解决惊群效应的?

什么是惊群效应? 第一次听到的这个名词的时候觉得很是有趣,不知道是个什么意思,总觉得又是奇怪的中文翻译导致的。 复杂的说(来源于网络)TLDR; 惊群效应(thundering herd)是指多进程&#xff…

十年软件测试老程序告诉你性能测试的左移右移到底能干嘛

常规的性能测试一般都是在测试阶段集成测试时候才开始介入,很容易测试时间不够,可不可以借鉴测试左移右移的思路,更早的介入和发现性能风险,然后在测试阶段更专注于分析优化? 借着这个问题,结合自己的实践…

孙哥Spring源码第29集

第29集 解析事务属性中的传播属性 【视频来源于:B站up主孙帅suns Spring源码视频】【微信号:suns45】 1、事务属性有哪些? 1、事务属性2、传播属性3、只读属性 设置事务为只读,提高事务运行的效率 false 4、超时属性 超时属性 通…

WPS的JS宏基础(三)——运算符

1、算术运算符 运算符是在编写代码时,最常用的符号。从本节课开始,运算符主要分为:算术运算符、连接运算符、比较运算符、逻辑运算符、赋值运算符等。我们将讲解这些常见的运算符,本节课讲解的是算术运算符。 符号作用加-减*乘/…

振南技术干货集:深入浅出的Bootloader(4)

注解目录 1、烧录方式的更新迭代 1.1 古老的烧录方式 (怀旧一下,单片机高压烧录器。) 1.2 ISP 与ICP 烧录方式 (还记得当年我们玩过的 AT89S51?) 1.3 更方便的 ISP 烧录方式 1.3.1串口 ISP (是 STC 单片机成就了我们,还是我们成就了…

MySQL事务详解

概述 事务是作为一个逻辑单元执行的一系列操作,一个逻辑工作单元必须有四个属性,称为ACID(原子性、一致性、隔离性和持久性)属性,只有这样才能成为一个事务。 我们的数据库一般都会并发执行多个事务,多个…