2

チェスの状況をモデル化するための小さなクラスのセットで、位置を表すクラスを作成したいと思いました。しかし、システムが同じ位置に対して複数のオブジェクトを作成しないように、有効な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);
}

私が考えることができる代替案

columnsとsのエラーチェックを追加し、2つの位置の名前が等しい場合にtrueを返すようrowに演算子をオーバーロードして、位置を適切に比較します。==このシナリオで同じ位置に多数のオブジェクトを作成するのは少し怖いですが、これは初期の最適化かもしれません。

したがって、問題は、このクラスを(Mooを使用して)設計するためのより良い方法があるかどうかです。TIA!:)

4

1 に答える 1

2

私はおそらく Create() メソッド (new X... の代わりに) を持ち、Create() 内にコードがあるため、正当な位置のみが作成されます。その位置で Create() を再度呼び出そうとすると、その位置の現在の位置オブジェクトを返すようにすることもできます。

また、誤って位置オブジェクトを直接作成することが心配な場合は、実際の位置クラスを Create()-ing クラスの非表示の子クラスにすることもできます。

于 2012-11-09T20:00:00.990 に答える