如何在使用MVC模型的Perl Tk (Tkx) GUI编程中避免全局变量



我有一个旧的非常大的Perl Tk GUI应用程序,我正在将其重构为Tkx。我想把接口分成几个包,这样我就可以以模块化的方式构建应用程序UI。另外,我想保持视图与模型的分离,使用控制器提供两者之间的接口。

在我看来,设计它的唯一方法是使用两个巨大的全局变量,一个保存模型($ model),另一个保存对分布在许多包中的小部件($UI)的引用。然后,Controller使用如下一系列命令将两者连接起来:

$UI->{'entry_widget'}->configure(-variable=>$MODEL->{'entry_value'});
$UI->{'button_widget'}->configure(-command=>sub {$MODEL->{'entry_value'} = "New Value"} );

我的问题是:有没有更好的方法来设计应用程序,避免使用这两个大的全局变量($UI和$MODEL)?欢迎提出任何建议。

我认为包方法是一种使全局可用的方法,但不是全局变量。所以像这样可以:

package MVC;
use strict;
use warnings;
use Scalar::Util qw<refaddr>;
my %MVCs;
sub _domain { 
    my ( $domain_name, $ref, $value ) = @_;
    my $r = $MVCs{ $key }{ $domain_name };
    return unless $$r or ref( $value );
    if ( ref $value ) {
        $$r = $value;
    }
    return $$r;
}
sub model      { shift; return _domain( 'model', @_ ); }
sub controller { shift; return _domain( 'controller', @_ ); }
sub view       { shift; return _domain( 'view', @_ ); }

所以在包外,你只需要调用这个:

my $controller = MVC->controller( $self ); 

获取与对象关联的控制器。

您甚至可以在访问器中添加一些导出逻辑,如:

unless ( $ref->can( $domain_name )) { 
    not strict 'refs';
    *{ ref( $ref ) . "::$domain_name" } 
        = sub { _domain( $domain_name, $ref ) }
        ;
}

你可以这样写:

$self->view->view_method( @args );

您不希望避免全局变量,您希望使用方法,即用$model->data$self->model->data替换$hashref->{data},其中$model$self是传递给信号处理程序/回调/命令的参数(或Axeman演示的"单例"),而不是您直接访问的哈希值

你使用方法来修改$model,因为方法可以拒绝用无意义/不正确的数据更新模型,它们确保你没有试图用垄断货币支付

你的应用程序总是会创建一个模型变量和一个视图变量,并通过参数传递将它们连接起来(可能通过中介,控制器)

它们不必是perl意义上的实际全局变量(处理作用域),它们可以是my $variables并且仍然可以很好地工作,就像你现在使用它们的方式(通过闭包),并且你避免了http://perl.plover.com/varvarname.html的问题,但是你没有得到智能模型的好处,知道他们需要什么样的燃料(柴油或无铅);将视图连接到模型需要更多类型

参见什么是模型视图演示器?

相关内容

  • 没有找到相关文章

最新更新