2012-11-09 5 views
2

체스 상황을 모델링하기위한 작은 클래스 집합에서 위치를 나타내는 클래스를 만들고 싶습니다. 그러나 나는 올바른 64 개의 위치 만 만들고 (그리고 내보내기), 시스템이 같은 위치에 대해 여러 개의 객체를 생성하지 못하도록하기 위해 생성자를 비공개로 만들고 싶었습니다. 기본적으로 싱글 톤이지만 1 = 64입니다. 64 톤입니다. 거의.n-gleton 패턴을 사용하여 고유 한 n 개의 항목을 나타내고 (내보내는)?

가능한 사용 :

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 초 동안 에러 체크를 추가하고 두 위치의 이름은 true의 경우 반환 할 == 연산자를 오버로드하는 것입니다 생각할 수있는 position을 적절하게 비교하는 것과 같습니다. 이 시나리오에서 동일한 위치에 많은 수의 객체를 작성하는 데 약간 겁이납니다. 그러나 이것은 초기 최적화 일 수 있습니다.

따라서이 클래스를 디자인하는 더 좋은 방법이 있다면 (Moo 사용) 문제가됩니다. 티아! :)

+1

어쩌면 자바 프로그래밍의 여름이 지나치게 복잡해질 수도 있습니다. :/ – memowe

답변

2

아마도 Create() 메서드 (새 X ... 대신)를 사용하여 Create() 내부에 코드가 있어야 합법적 인 위치 만 만들 수 있습니다. 해당 위치에서 Create()를 다시 호출하려고하면 해당 위치에 대한 현재 위치 객체를 반환 할 수도 있습니다.

실수로 위치 개체를 직접 만들지 걱정되는 경우 실제 위치 클래스를 Create() 클래스의 숨겨진 자식 클래스로 만들 수도 있습니다.

+0

감사합니다. :) 나는 그 '창조'아이디어를 좋아한다. – memowe