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
    @Override
    protected 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";

    @Override
    protected 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源码设计模式解析与实战第二版

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

6-8.4V输入 双节锂电输入 输出19V 1.5-2A 外置MOS 大电流升压芯片

6-8.4V输入 双节锂电输入 输出19V 1.5-2A 外置MOS 大电流升压芯片

C++:OJ练习(每日练习!)

编程题: 题一:计算日期到天数的转换 计算日期到天数转换_牛客题霸_牛客网 (nowcoder.com) 示例1 输入: 2012 12 31 输出: 366 思路一: 第一步:创建年,月,日的变量,并按…

如何正确使用 JavaScript 中的 slice() 方法

在 JavaScript 中,slice() 是一个常用的数组方法,用于从现有数组中提取一部分元素,然后返回一个新的数组。它是一个非常有用的工具,可以帮助你在不改变原始数组的情况下操作数组的子集。本文将介绍 slice() 的基本概念、使用方法、…

阿里云+宝塔部署项目(Java+React)

阿里云服务器宝塔面板部署项目(SpringBoot React) 1. 上传所需的文件到服务器 比如jdk包和java项目的jar:这里以上传jar 为例,创建文件夹,上传文件; 在创建的文件夹下上传jar包 上传jdk 2. 配置jdk环境 3.…

No201.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

【游戏开发算法每日一记】使用随机prime算法生成错综复杂效果的迷宫(C#,C++和Unity版)

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:Uni…

java实现选择排序

算法步骤 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。重复第二步,直到所有元素均排序完毕。 动图演…

【Linux网络】ssh服务与配置,实现安全的密钥对免密登录

目录 一、SSH基础 1、什么是ssh服务器 2、对比一下ssh协议与telnet协议 3、常见的底层为ssh协议的软件: 4、拓展 二、SSH软件学习 1、ssh服务软件学习 2、sshd公钥传输的原理: 3、ssh命令学习: 4、学习解读sshd服务配置文件&#x…

自定义Matplotlib中的颜色映射(cmap)

要自定义Matplotlib中的颜色映射(cmap),您可以按照以下步骤进行操作: 导入所需的库: import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import LinearSegmentedColormap创建自定义颜色映…

一篇博客读懂栈——Stack

目录 一、栈的概念与结构 1.1栈的概念 1.2栈的结构 二、栈的实现 2.1开始前准备stack.h 2.2栈的初始化STInit 2.3栈的销毁STDestroy 2.4栈顶插入STPush 2.5栈顶删除STPop 2.6取栈顶元素STTop 2.7检查栈是否为空STEmpty 2.8栈的元素个数STSize 一、栈的概念与结…

房产中介租房小程序系统开发搭建:详细指南教你如何构建

随着微信小程序的日益普及,越来越多的企业和个人开始尝试开发自己的小程序。以下是制作一个房地产微信小程序的详细教程,希望对大家有所帮助。 一、注册登录乔拓云平台,进入后台 首先,需要注册并登录乔拓云平台,该平台…

JavaEE初阶(18)(JVM简介:发展史,运行流程、类加载:类加载的基本流程,双亲委派模型、垃圾回收相关:死亡对象的判断算法,垃圾回收算法,垃圾收集器)

接上次博客:初阶JavaEE(17)Linux 基本使用和 web 程序部署-CSDN博客 目录 JVM 简介 JVM 发展史 JVM 运行流程 JVM的内存区域划分 JVM 执行流程 堆 堆的作用 JVM参数设置 堆的组成 垃圾回收 堆内存管理 类加载 类加载的基本流…

Vue事件绑定

目录 前言 Vue事件处理 指令的语法格式 事件绑定指令—v-on 回调函数 前言 我们知道如何在原生js中实现事件绑定&#xff0c;那在vue中如何实现呢&#xff1f; Vue事件处理 指令的语法格式 <标签 v-指令名&#xff1a;参数名"表达式">{{插值语法}}</…

MQ四大消费问题一锅端:消息不丢失 + 消息积压 + 重复消费 + 消费顺序性

RabbitMQ-如何保证消息不丢失 生产者把消息发送到 RabbitMQ Server 的过程中丢失 从生产者发送消息的角度来说&#xff0c;RabbitMQ 提供了一个 Confirm&#xff08;消息确认&#xff09;机制&#xff0c;生产者发送消息到 Server 端以后&#xff0c;如果消息处理成功&#xff…

WebGl-Blender:建模 / 想象成形 / 初识 Blender

一、理解Blender 欢迎来到Blender&#xff01;Blender是一款免费开源的3D创作套件。 使用Blender&#xff0c;您可以创建3D可视化效果&#xff0c;例如建模、静态图像&#xff0c;3D动画&#xff0c;VFX&#xff08;视觉特效&#xff09;快照和视频编辑。它非常适合那些受益于…

解密网络世界的秘密——Wireshark Mac/Win中文版网络抓包工具

在当今数字化时代&#xff0c;网络已经成为了人们生活和工作中不可或缺的一部分。然而&#xff0c;对于网络安全和性能的监控和分析却是一项重要而又复杂的任务。为了帮助用户更好地理解和解决网络中的问题&#xff0c;Wireshark作为一款强大的网络抓包工具&#xff0c;应运而生…

Python基础入门----如何使用 Pipenv 在项目目录中创建虚拟环境

文章目录 引言Pipenv 简介安装 Pipenv在项目目录中创建虚拟环境1. 进入你的项目目录2. 设置环境变量3. 创建虚拟环境4. 激活虚拟环境结论引言 在Python开发中,使用虚拟环境是一种良好的实践,它可以帮助开发者管理项目的依赖,并避免不同项目间的依赖冲突。Pipenv 是一个流行…

nginx安装搭建

下载 免费开源版的官方网站&#xff1a;nginx news Nginx 有 Windows 版本和 Linux 版本&#xff0c;但更推荐在 Linux 下使用 Nginx&#xff1b; 下载nginx-1.14.2.tar.gz的源代码文件&#xff1a;wget http://nginx.org/download/nginx-1.14.2.tar.gz 我的习惯&#xff0…

【excel技巧】如何取消excel隐藏?

Excel工作表中的行列隐藏了数据&#xff0c;如何取消隐藏行列呢&#xff1f;今天分享几个方法给大家 方法一&#xff1a; 选中隐藏的区域&#xff0c;点击右键&#xff0c;选择【取消隐藏】就可以了 方法二&#xff1a; 如果工作表中有多个地方有隐藏的话&#xff0c;还是建…

专业调色软件 3D LUT Creator Pro 激活中文 for mac

3D LUT Creator与彩 色 图 像一起工作的简单性和清晰度不会让任何人无动于衷。此外&#xff0c;扩展名为.3dl的文件可以导入到Adobe Photoshop&#xff0c;因此您可以将这些设置作为调整图层应用&#xff0c;不仅可以将它们应用于位图图像&#xff0c;还可以将其应用于矢量图形…