在一组用于建模国际象棋情境的类中,我想构建一个表示位置的类。但我想创建(并导出)仅有效的64个位置,并在此之后使构造函数为私有,以防止系统为同一位置创建多个对象。基本上是单身,但是1 = 64.一个64吨。那种。
可能的用法:
use Positions; # exports positions
my $pos = e4;
# something happens...
do_foo() if $pos == d5;
do_bar() if $pos->row == 8;
我的解决方案以我想要的方式工作,但感觉有点不雅和过度设计。
基本:
package Position;
use Moo;
has column => (is => 'ro');
has row => (is => 'ro');
has name => (is => 'lazy');
sub _build_name {
my $self = shift;
return $self->column . $self->row;
}
sub to_string { shift->name }
# ...
对于isa
的有效列或行,没有错误检查,因为我不希望类用户完全实例化位置对象。现在到出口:
# prepare 64 positions
my %position;
foreach my $col ('a' .. 'h') {
foreach my $row (1 .. 8) {
# build
my $name = "$col$row";
my $pos = Cherl::Position->new(column => $col, row => $row);
# remember
$position{$name} = $pos;
}
}
# export
sub import {
my $class = shift;
my $caller = caller;
# magic!
no strict 'refs';
for my $name (sort keys %position) {
*{$caller . '::' . $name} = sub { $position{$name} };
}
}
# make it private
sub BUILDARGS {
my ($class, @args) = @_;
die 'private' unless +(caller 1)[0] eq __PACKAGE__;
return $class->SUPER::BUILDARGS(@args);
}
我能想到的替代方案
将添加column
和row
s的错误检查,并重载==
运算符,如果两个位置的名称等于正确比较位置,则返回true。在这种情况下,我有点害怕为同一个位置构建大量对象,但这可能是早期优化。
所以问题是,是否有更好的方法来设计这个类(使用Moo)。 TIA! :)
答案 0 :(得分:2)
我可能有一个Create()方法(而不是新的X ...),其中的代码在Create()中,因此它只会创建合法的位置。如果你试图再次在该位置调用Create(),你甚至可以让它返回该位置的当前位置对象。
另外,如果您担心意外直接创建位置对象,甚至可能会将实际位置类设为Create() - ing类的隐藏子类。