Matlab 实现命令模式实例(面向对象编程)

matlab实现面向对象编程与matlab本身的定位是冲突的,可能实际的用处并不大,但是依然值得学习一下。本文系原创,以一则简单实例实现经典的命令模式,供新手学习参考。

STEP 0 新建一个文件夹

新建一个文件夹作为本例的工作文件夹。本例的每一个“类”,都被保存为一个独立的.m文件,存放在该文件夹中。

STEP 1 构建命令执行的对象

对象是类的具体实例。此处构建的实际是可用于命令执行的类。例如,一个学生必然有自己的名字和年龄,这里学生就可以抽象为一个类,学生的名字和年龄就是这个类的属性,更改学生的名字和年龄就是可执行的“命令”。代码如下:

classdef Student < handle
    properties(Access=public)
        name string
        age double{mustBeNonnegative}
    end
    methods
        function obj=Student(Name,Age)
            obj.name=Name;
            obj.age=Age;
        end
        function selfIntroduc(obj)
            disp([obj.name num2str(obj.age)])
        end
    end
end

STEP 2 构建命令基类(命令接口)

matlab支持抽象类和类的继承。通过定义一个抽象的基类实现“接口”功能。代码如下:

classdef Command < handle
    methods(Abstract)
        execute(obj,el);
        undo(obj);
    end
end

STEP 3 将具体命令封装成类(命令类)

为了解耦,需要将具体的命令封装成类,并且把命令执行的对象作为参数进行传递。也就是具体的命令可以由不同的执行对象进行执行,取决于在实例化命令类时传递进来的参数。在这一步,其实把命令内容和命令执行对象进行解耦。通过类的继承,获得统一的命令接口。的代码如下:

%"改名字"命令封装成类(接口继承自step2 的 Command 类)
classdef cmdChangeName < Command
    properties(Access=private)
        std Student
        oldname
        getname
    end
    methods
        function obj=cmdChangeName(Std)
            obj.std=Std;
        end
        function funcGetName(obj,Name)
            obj.getname=Name;
        end
        function execute(obj)
            obj.oldname=obj.std.name;
            obj.std.name=obj.getname;
        end
        function undo(obj)
            obj.std.name=obj.oldname;
        end
    end
end

STEP 4 构建命令队列(实例化命令的容器)

同样是为了解耦,需要构建命令队列,也就是将每一个需要执行的实例化的命令按照执行顺序依次收纳到一个容器中。命令模式下,命令队列负责接受需要执行的命令,并将命令加入队列(但是不关心命令的请求者);同时命令队列还负责触发命令的执行(但是不关心命令的执行结果)。也就是这一步实现了命令请求与命令执行的解耦(收到命令请求就加入队列,不管请求者是否还存在;触发命令执行后也不去管命令是否执行完,当然matlab环境下一定会等待命令执行完成)。代码如下:

classdef cmdInvoker
    properties(Access=private)
        commands myStack
    end

    methods
        function obj=cmdInvoker()
            obj.commands=myStack();
        end
        function runCMD(obj,Cmd)
            Cmd.execute();
            obj.commands.push(Cmd);
        end
        function undo(obj)
            if obj.commands.size>0
                temC=obj.commands.pop;
                temC.undo;
            else
            end
        end
    end
end

补充说明: matlab没有或类似于“栈”的队列数据形式,本例自定义了一个类似的类。
代码如下:
本段代码参考文章:Matlab 类实例 队列的实现)

classdef myStack <handle  
properties (Access = private)
    data
    count
    capacity
end
methods
    function obj = myStack(c)        
        switch nargin
            case 0
                c=100;
            otherwise
        end
        obj.data = cell(c, 1);
        obj.count = 0;
        obj.capacity = c;
    end
    function s=sizeStack(obj)
        s=obj.count;
    end 
    function clearStack(obj) 
        obj.count = 0;
    end
    function push(obj, el)
        if obj.count==obj.capacity
            temC=obj.data;
            obj.data=cell(obj.capacity+100,1);
            obj.capacity=obj.capacity+100;
            for iter=1:1:obj.count
                obj.data{iter}=temC(iter);
            end
        else
        end
        obj.data{obj.count+1} = el;
        obj.count = obj.count + 1;
    end 
    function el = pop(obj) 
        if obj.count == 0
            el=[];
        else
            el = obj.data{obj.count};
            obj.count = obj.count - 1;
        end             
    end 
    function remove(obj) 
        obj.count=obj.count-1;
    end
end
end

STEP 5 客户端(对上述命令模式的检测)

如题,代码如下:

clc;clear all;

%实例化命令执行的对象
S=Student('A',18);
S.selfIntroduc();

%实例化命令队列
I=cmdInvoker();

%实例化需要执行的命令command1和command2
command1=cmdChangeName(S);
command1.funcGetName('B');

command2=cmdChangeName(S);
command2.funcGetName('C');

%将命令添加到命令队列并触发执行(添加和触发执行是同步的,也可以不同步)
%命令队列还会同步记录命令执行前对象的状态,实现撤销或日志功能
I.runCMD(command1);
S.selfIntroduc();
I.runCMD(command2);
S.selfIntroduc();
I.runCMD(command1);
S.selfIntroduc();
I.undo;
S.selfIntroduc();
I.undo;
S.selfIntroduc();

完结

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值