加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

actionscript-3 – 命令模式和AS3

发布时间:2020-12-15 07:27:26 所属栏目:百科 来源:网络整理
导读:只是好奇你们如何解决封装命令的问题.您是否为每个命令创建一个单独的类?或者还有另一种方式(没有大量的课程)? 请注意,我正面临着动作脚本3的问题. Upd:更确切地说,我想知道如何组织命令相关的机器(例如每个命令的类). 先感谢您! 解决方法 命令模式是关
只是好奇你们如何解决封装命令的问题.您是否为每个命令创建一个单独的类?或者还有另一种方式(没有大量的课程)?

请注意,我正面临着动作脚本3的问题.

Upd:更确切地说,我想知道如何组织命令相关的机器(例如每个命令的类).

先感谢您!

解决方法

命令模式是关于分离三个不同类别的对象之间的关注点:

>祈求者
>接收者
>命令

正如wvxvw所指出的那样,通常意味着你有一个实现ICommand的TON类,它实际上只是作为调用接收器上方法的代理工作 – 这是Java所必需的.随着时间的推移,这会变得有点难以管理.

但是让我们看一些代码,我将按照示例代码介绍找到的命令模式的基础知识here,但为了清晰起见略有简化:

所以首先是接收器:

// Receiver
public interface IStarShip {
    function engage():void;
    function makeItSo():void;
    function selfDestruct():void;
}

public class Enterprise implements IStarShip {
    public function Enterprise() { }

    public function engage():void {
        trace(this,"Engaging");
    }

    public function makeItSo():void {
        trace(this,"Making it so");
    }

    public function selfDestruct():void {
        trace(this,"Self Destructing");
    }
}

和调用者:

// invoker
public class CaptPicard {
    private var _command:ICommand;

    public function CaptPicard() { }

    public function set command(cmd:ICommand):void {
        this._command = cmd;
    }

    public function issueCommand():void {

    }
}

最后一些命令:

// command
public interface ICommand {
    function execute():void;
}

public class EngageCommand implements ICommand 
{
    private var receiver:IStarShip

    public function EngageCommand(receiver:IStarShip) {
        this.receiver = receiver;
    }

    public function execute():void {
        receiver.engage();
    }
}

public class SelfDestructCommand implements ICommand 
{
    private var receiver:IStarShip

    public function SelfDestructCommand(receiver:IStarShip) {
        this.receiver = receiver;
    }

    public function execute():void {
        receiver.selfDestruct();
    }
}   

public class MakeItSoCommand implements ICommand 
{
    private var receiver:IStarShip

    public function MakeItSoCommand(receiver:IStarShip) {
        this.receiver = receiver;
    }

    public function execute():void {
        receiver.makeItSo();
    }
}

我们可以通过以下方式来解决这些问题:

var enterprise:Enterprise = new Enterprise;
var picard:CaptPicard = new CaptPicard();
picard.command = new SelfDestructCommand(enterprise);
picard.issueCommand();

到目前为止,它与示例代码紧密相关,并且是ActionScript中命令模式的非常标准的实现.但是,现在我们有三个ICommand实现,并且随着接收器可以增加的数量增加,编排模式所需的命令数量也会增加.

如果我们开始检查Command本身,除了告诉接收器做一些工作之外,它并没有做太多其他事情.正如wvxvw暗示的那样,动作脚本中已经有了这样的功能:一流的功能.

让我们看看可能的实现,以减少你需要浮动的ICommand的实现数量,而不需要改变你的模式.

让我们说我们制作了一个通用类型的命令,让我们说:

public class GenericCommand implements ICommand {

    private var worker:Function;

    public function GenericCommand(worker:Function) {
        this.worker = worker;
    }

    public function execute():void {
        this.worker.call();
    }
}

请注意,我们的新类型仍然实现ICommand,但它不接受直接绑定到某个实现,而是接受一个worker来做一些工作.它不会立即执行它,它只是坚持它并等待其他东西使它运动.

然后我们可以将代码切换为这样的代码:

var enterprise:Enterprise = new Enterprise;
var picard:CaptPicard = new CaptPicard();
picard.command = new GenericCommand(function() { enterprise.selfDestruct(); });
picard.issueCommand();
picard.command = new GenericCommand(function() { enterprise.engage(); });
picard.issueCommand();
picard.command = new GenericCommand(function() { enterprise.makeItSo(); });
picard.issueCommand();

使用这一个GenericCommand,我们可以将所有命令展开到这个新模式中(或者在它们之间混合和匹配).

但是如果你仔细观察,你可以看到,通过使用它,我们通过引用封闭的变量企业将一个通用命令紧密地耦合到IStarShip,或许更令人担心的是,如果我们不小心,我们可以创造一吨这些关闭.它们都需要在某些时候进行垃圾收集,这可能会影响性能,或者更糟糕的是导致内存泄漏.

我们可以将这一层更多地分离,使其更具动态性.我们可以使用工厂模式来帮助动态生成命令,而不是直接关闭到本地变量企业.考虑一下:

public class StarShipCommandFactory {
    private var worker:Function;

    public function StarShipCommandFactory(worker:Function) {
        this.worker = worker;
    }

    public function to(receiver:IStarShip):ICommand {
        return new GenericCommand(function() {
            worker.call(undefined,receiver);
        });
    }
}

然后我们可以使用它来创建一个命令工厂来创建这些命令.就像是:

var enterpriseA:Enterprise = new Enterprise();
var enterpriseB:Enterprise = new Enterprise();
var picard:CaptPicard = new CaptPicard();

var selfDestuctor:StarShipCommandFactory = new StarShipCommandFactory(function(starShip:IStarShip):void {
    starShip.selfDestruct();
} );

var blowUpA:ICommand = selfDestructor.to(enterpriseA);
var blowUpB:ICommand = selfDestructor.to(enterpriseB);

picard.command = blowUpA;
picard.issueCommand();

picard.command = blowUpB;
picard.issueCommand();

这将减少需要生成的静态类的数量,以利用属性第一类函数的动态创建的对象,但仍然应用相同的一般概念.

实际上,使用这种模式,您可以构建非常复杂的命令,代理多个接收器上的多个动作,这可能是一个非常强大的功能.

你为什么要使用ICommand的传统实现呢?

坚持传统模式的最大原因之一是易于序列化.因为对象是显式的,所以它们很容易序列化.所以,假设你有一堆Vector.< ICommand>.您可以轻松地序列化它们,将它们写出来,然后再重新加载它们并按顺序重放它们,并且应该处于与您完全相同的状态.动态生成的对象就像我之前描述的对象一样有点棘手 – 不是不可能,只是比较棘手.

如果您担心维护大量映射到接收器操作的ICommands,那么在过去我使用元编程来解决这个问题.使用ruby / python解析一定数量的文件,并自动生成ICommand映射.它们很多时候都是相当天真的实现,它们是自动化的主要候选者.

无论如何,这些是我对这个问题的看法.你可以做很多事情来帮助简化你的代码 – 我刚刚触及了表面.您的里程可能会有所不同 – 请记住:“找到解决问题的模式,而不是反过来” – 但也许您可以从中收集一些有用的信息.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读