Android设计模式--原型模式

news2024/12/30 3:43:01

一,定义

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

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

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

二,使用场景

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

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

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

相关文章

YOLO目标检测——苹果数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用:监测果园中苹果的生长情况、水果品质监控、自动化分拣数据集说明:苹果检测数据集,真实场景的高质量图片数据,数据场景丰富标签说明:使用lableimg标注软件标注,标注框质量高,含voc(…

淘宝京东优惠券信息API接口系列

获取淘宝优惠券信息接口需要使用淘宝开放平台提供的API接口。以下是获取优惠券信息的步骤: 进入淘宝开放平台,注册并登录账号。在开放平台页面中,找到“优惠券”或“营销工具”等相关的API接口,根据需要进行选择。根据接口文档&a…

计算机组成原理:大而快——层次化存储

原文链接www.xiaocr.fun/index.php/2023/11/14/计算机组成原理大而快-层次化存储/ 引言 关于两种局部性 时间局部性:如果某个数据被访问,那么在不久的将来它可能再次被访问空间局部性:如果某个数据项被访问,与它相邻的数据项可…

接口自动化测试(Python+Requests+Unittest)合集详解教程

(1)接口自动化测试的优缺点 优点: 测试复用性。维护成本相对UI自动化低一些。回归方便。可以运行更多更繁琐的测试。 自动化的一个明显的好处是可以在较少的时间内运行更多的测试。为什么UI自动化维护成本更高? 因为前端页面变…

工作记录-------MySql主从同步

MySql主从同步简述: MySQL主从同步,可以实现将数据从一台数据库服务器同步到多台数据库服务器。MySQL数据库自带主从同步功能,经过配置,可以实现基于库、表结构的多种方案的主从同步。 Redis是一种高性能的内存数据库&#xff1…

【Hello Go】初识Go语言

初识Go语言 Go语言介绍Go语言是什么Go语言优势Go语言能用来做什么 Go语言环境安装第一个GO语言程序运行Go语言程序 Go语言介绍 Go语言是什么 go语言是是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言. 静态类型:在静态类型…

【左程云算法全讲10】打表技巧和矩阵处理技巧

系列综述: 💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:材料主要源于左程云算法课程进行的,每个知识点的修正和深入主要参考…

算法笔记-其他高效的技巧与算法(未处理完)

算法笔记-其他高效的技巧与算法 前缀和 前缀和 #include <cstdio> #include <vector> using namespace std; const int MAXN 10000; int n, a[MAXN]; int sum[MAXN] { 0 };int main() {scanf("%d", &n);for (int i 0; i < n; i) {scanf("…

数据银行:安全保障的重要一环

随着信息技术的快速发展&#xff0c;数据银行已经成为了我们日常生活中不可或缺的一部分。它存储了我们的个人信息、财务数据、医疗记录等重要信息&#xff0c;这些信息对于我们的生活和工作至关重要。然而&#xff0c;由于数据的安全性备受关注&#xff0c;因此&#xff0c;对…

JavaWeb——HTML常用标签

目录 1. 标题标签 2. 段落标签 3. 换行/分割线标签 4. 列表标签 4.1. 有序列表 4.2. 无序列表 5. 超链接标签 6. 多媒体标签 6.1. img 图片标签 6.2. audio 音频标签 6.3. video 视频标签 7. 表格标签(重点) 8. 表单标签&#xff08;重点&#xff09; 1. 标题标签 …

【unity插件】UGUI的粒子效果(UI粒子)—— Particle Effect For UGUI (UI Particle)

文章目录 前言插件地址描述特征Demo 演示如何玩演示对于 Unity 2019.1 或更高版本对于 Unity 2018.4 或更早版本 用法基本上是用法使用您现有的 ParticleSystem 预制件带 Mask 或 RectMask2D 组件脚本用法UIParticleAttractor 组件开发说明常见问题解答&#xff1a;为什么我的粒…

计算机组成原理——指令系统题库21-40

21、假定指令地址码给出的是操作数的存储地址&#xff0c;则该操作数采用的是什么寻址。 A、 立即    B、 直接     C、 基址     D、 相对 22、寄存器间接寻址方式的操作数存储在什么中 A、 通用寄存器    B、 存储单元     C、 程序计数器     …

error: C3867: “MainWindow::copyFileCallBack”: 非标准语法;请使用 ““

error: C3867: “MainWindow::copyFileCallBack”: 非标准语法&#xff1b;请使用 “&” 这时候我们按照提示将t.testFun前面加上&又会出现error C2276: “&”: 绑定成员函数表达式上的非法操作&#xff0c; 解决 在函数前面加上static声明

MySQL(16):变量、流程控制与游标

变量 在MySQL数据库的存储过程和函数中&#xff0c;可以使用变量来存储查询或计算的中间结果数据&#xff0c;或者输出最终的结果数据。 在 MySQL 数据库中&#xff0c;变量分为 系统变量 以及 用户自定义变量 。 系统变量 变量由系统定义&#xff0c;不是用户定义&#xff…

缩点+图论路径网络流:1114T4

http://cplusoj.com/d/senior/p/SS231114D 重新梳理一下题目 我们先建图 x → y x\to y x→y&#xff0c;然后对点分类&#xff1a;原串出现点&#xff0c;原串未出现点。 假如我们对一个原串出现点进行了操作&#xff0c;那么它剩余所有出边我们立刻去操作必然没有影响。所…

由于找不到msvcp140.dll无法继续执行代码有哪些解决方法

msvcp140.dll是Microsoft Visual C 2015 Redistributable的一个组件&#xff0c;它是运行许多Windows应用程序所必需的。当msvcp140.dll丢失或损坏时&#xff0c;可能会导致以下问题&#xff1a; 1. 程序无法启动或崩溃。 2. 系统出现错误提示&#xff0c;如“找不到msvcp140…

SQL-LABS

less8 and 11-- 12 发现存在注入点 接下来我们会接着用联合查询 和以往的题目不一样没显错位&#xff0c;也就是没有报错的内容&#xff0c;尝试用盲注 布尔型 length&#xff08;&#xff09;返回长度 substr&#xff08;&#xff09;截取字符串&#xff08;语法substr&a…

取消Element UI响应式设计——打造固定布局的菜单

引言 在当今的Web开发中&#xff0c;响应式设计已经成为了一个不可或缺的部分。然而&#xff0c;有时候我们可能需要取消这种响应式特性&#xff0c;尤其是对于一些特定的界面元素&#xff0c;如导航菜单。在Element UI框架中&#xff0c;导航菜单&#xff08;el-menu&#xff…

c++范围for语句

语法格式 for(declaration:expression)statement 基本使用 遍历输出 vector<int> nums { 1,2,3,4,5}; for (int num : nums) {num;cout << num << " "; } cout << endl; 遍历时修改 vector<int> nums { 1,2,3,4,5}; for (int&…