原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。Matlab面向对象编程有两种类,一种是Value Class,一种是Handle Class,Value对象深拷贝的直接通过赋值语句即可实现(实际上是Lazy Copy),如下所示:

ValueA.m

classdef ValueA
properties
name
end
methods
function obj = ValueA(name)
obj.name = name;
end
end
end

测试代码:

Handle类是引用类,相当于Java的引用变量,变量指向具体的地址,Handle对象的赋值操作实际上只是浅拷贝,没有拷贝对象的实际数据。如下图所示:

RefB.m

classdef RefB < handle
properties
name
end
methods
function obj = RefB(name)
obj.name = name;
end
end
end

测试代码:

注:一个类如果同时继承Value类和Handle类时,需要在Value基类加上关键词HandleCompatible,使之成为Handle兼容类,如下所示,BaseV仍是Value类,继承后的派生类是Handle类。(如果两个基类都是Value类,至少有一个是Handle兼容类,则继承这两个基类的派生类仍是Value类)

classdef(HandleCompatible) BaseV
end

此外,(1)Handle兼容类的所有基类必须是Handle兼容类。(2) HandleCompatible不能被继承。(3)如果在一个类定义中明确设置了HandleCompatible为false,则该类所有基类中不能有Handle类。(4)如果一个类定义没有明确设置了HandleCompatible特性,而有一个基类是Handle类,则所有基类必须是Handle兼容类。

出于项目的实际需要,需要对handle类进行深拷贝,可以仿照Java的原型模式在handle类中加入clone方法:

RefA.m

classdef RefA < handle
properties
name
refB
end
methods
function obj = RefA()
end
function copyobj = clone(obj)
copyobj = RefA();
copyobj.name = obj.name;
copyobj.refB = obj.refB.clone();
end
end
end

RefB.m

classdef RefB < handle
properties
name
end
methods
function obj = RefB()
end
function copyobj = clone(obj)
copyobj = RefB();
copyobj.name = obj.name;
end
end
end

test1.m

a = RefA();
a.name = 'a-name';
a.refB = RefB();
a.refB.name = 'a-rb-name';
b = a.clone();
b.refB.name = 'b-rb-name';
disp(b.refB.name);
disp(a.refB.name);

结果:

如果要克隆多个属性,可以借助meta.class来实现:

RefAA.m

classdef RefAA < handle
properties
name
refBB
end
methods
function obj = RefAA()
end
function copyobj = clone(obj)
copyobj = RefAA();
metaobj = metaclass(obj);
props = {metaobj.PropertyList.Name};
for i = 1:length(props)
prop = obj.(props{i});
if(isa(prop,'handle'))
copyobj.(props{i}) = prop.clone();
else
copyobj.(props{i}) = prop;
end
end
end
end
end

RefBB.m

classdef RefBB < handle
properties
name
end
methods
function obj = RefBB()
end
function copyobj = clone(obj)
copyobj = RefBB();
metaobj = metaclass(obj);
props = {metaobj.PropertyList.Name};
for i = 1:length(props)
prop = obj.(props{i});
if(isa(prop,'handle'))
copyobj.(props{i}) = prop.clone();
else
copyobj.(props{i}) = prop;
end
end
end
end
end

test2.m

a = RefAA();
a.name = 'a-name';
a.refBB = RefBB();
a.refBB.name = 'a-rb-name';
b = a.clone();
b.refBB.name = 'b-rb-name';
disp(b.refBB.name);
disp(a.refBB.name);

运行结果

另外在Matlab R2011a开始,可以使用matlab.mixin.Copyable自动克隆一个对象,可以利用copy函数来实现对象的克隆。这类似于Java的Cloneable类。不过不能对属性做递归的深拷贝,如果要实现深拷贝,需要重写copyElement方法,代码如下:

AH.m

classdef AH < matlab.mixin.Copyable
properties
name
bh
end
methods(Access = protected)
function copyobj = copyElement(obj)
copyobj = copyElement@matlab.mixin.Copyable(obj);
metaobj = metaclass(obj);
props = {metaobj.PropertyList.Name};
for i = 1:length(props)
prop = obj.(props{i});
if(isa(prop,'handle'))
copyobj.(props{i}) = copy(prop);
end
end
end
end
end

BH.m

classdef BH < matlab.mixin.Copyable
properties
name
end
end

test3.m

a = AH();
a.name = 'a-name';
a.bh = BH();
a.bh.name = 'a-rb-name';
b = copy(a);
b.bh.name = 'b-rb-name';
disp(b.bh.name);
disp(a.bh.name);

测试结果:

注:

1、copy不会调用构造函数

2、copy函数是公有的,不可覆盖的

3、copy函数不会拷贝依赖属性成员

4、copy函数不会默认拷贝动态属性成员(addprop函数),动态属性成员的拷贝功能需要在派生类中实现

5、copy不会复制听众

6、枚举类不能是Copyable的派生类

7、析构函数delete调用copy时,会创建一个合法的副本

8、copy能拷贝已被delete过的句柄

Matlab原型模式的更多相关文章

  1. 设计模式(六)原型模式(Prototype Pattern)

    一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在 ...

  2. PHP 原型模式

    原型模式:原型模式是先创建好一个原型对象,然后通过拷贝原型对象来创建新的对象.适用于大对象的创建,因为创建一个大对象需要很大的开销,如果每次new就会消耗很大,原型模式仅需内存拷贝即可.也可以用作动态 ...

  3. C#设计模式:原型模式(Prototype)及深拷贝、浅拷贝

    原型模式(Prototype) 定义: 原型模式:用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.被复制的实例被称为原型,这个原型是可定制的. Prototype Pattern也是一 ...

  4. 设计模式--原型模式Prototype(创建型)

    一.原型模式 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象.原型模式实现的关键就是实现Clone函数,还需要实现深拷贝. 二.UML类图 三.例子 //父类 class Resume ...

  5. C#设计模式之原型模式

    原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象. 分析: 孙悟空:根据自己的形状复制(克隆)出多个身外身 软件开发:通过复制一个原型对象得到多个与原型对象一模一样的新对 ...

  6. 设计模式 之 原型模式(ProtoType)

    什么时原型模式   或   原型模式的定义: 用原型实例来指定创建对象的种类,并通过拷贝这些原型创建新的对象. 原型模式的特点: 1),它是面向接口编程, 2),原型模式的新对象是对原型实例的一个克隆 ...

  7. Objective-C 原型模式 -- 简单介绍和使用

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建 ...

  8. C#设计模式-原型模式

    在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配 ...

  9. C#设计模式系列:原型模式(Prototype)

    1.原型模式简介 1.1>.定义 原型模式(Prototype)用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象. 1.2>.使用频率 中 1.3>.原型模式应用 首先 ...

随机推荐

  1. linux pip

    $ wget https://bootstrap.pypa.io/get-pip.py$ python get-pip.py$ pip -V #查看pip版本 接下来就可以随便pip安装东西了 首先查 ...

  2. web页面引入字体

    一.常见web字体 TrueType (.ttf) Windows和Mac系统最常用的字体格式,其最大的特点就是它是由一种数学模式来进行定义的基于轮廓技术的字体,这使得它们比基于矢量的字体更容易处理, ...

  3. CentOS7静默安装Oracle 18g数据库(无图形化界面)

    说明: 因为是静默安装,所以我们不需要安装图形界面 准备:下载Oracle软件 官方网站:http://www.oracle.com/technetwork/database/enterprise-e ...

  4. 深入理解JVM虚拟机

    JVM平台上还可以运行其他语言,运行的是Class字节码.只要能翻译成Class的语言就OK了.挺强大的. JVM厂商很多 垃圾收集器.收集算法 JVM检测工具 关于类的加载: Java代码中,类型( ...

  5. EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器解决方案之Windows服务安装

    背景说明 EasyDSS流媒体解决方案是由安徽旭帆信息科技有限公司自主研发的一套集流媒体点播.转码.管理.直播.录像.检索.时移回看于一体的一套完整的商用流媒体解决方案.EasyDSS软件以压缩包的形 ...

  6. [转]Mathjax语法总结

    链接地址:https://blog.csdn.net/ajacker/article/details/80301378

  7. PPT使用技巧

    推荐两个个人收藏的网站站点(非广告,好东西就应该share) 免费PPT模板下载网站 http://www.1ppt.com 免费图标下载网站 https://www.easyicon.net 一.P ...

  8. vue使用px2rem

    配置 flexible 安装 lib-flexible 在命令行中运行如下安装: 1 npm i lib-flexible --save 引入 lib-flexible 在项目入口文件 main.js ...

  9. SignalR长连接的简单用法

    ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务 ...

  10. Activiti Service介绍

    原文地址:https://www.cnblogs.com/lyh421/p/6419518.html 第一章 认识Activiti 内容概览:讲解activiti的特点.接口概览.架构等基本信息. 1 ...