Как я могу кодировать фабрику в Perl и Американском лосе?

Выезд Соединение (SQL) на Википедию

  • Внутреннее объединение - Учитывая две таблицы, внутреннее объединение возвращает все строки, которые существуют в обеих таблицах
  • оставленный / правильное (внешнее) соединение - Учитывая две таблицы, возвращает все строки, которые существуют или в левой или правой таблице Вашего соединения, плюс строки с другой стороны будет возвращен, когда пункт соединения является соответствием или пустым указателем, будет возвращен для тех столбцов

  • Полный Внешний - Учитывая две таблицы, возвращает все строки и возвратится, аннулирует, когда любой левый или правый столбец не там

  • Перекрестные объединения - Декартово соединение и может быть опасным если не используемый тщательно

11
задан brian d foy 8 August 2009 в 01:07
поделиться

5 ответов

Ик. У Стевана есть очень веский аргумент, что новый всегда должен вернуть экземпляр класса. Все остальное сбивает с толку новых людей, которые учатся систему.

Возможно, вы захотите взглянуть на MooseX :: AbstractFactory . Если у вас это не сработает, то:

package FooBar;
use Moose;

has [qw(SUBCLASS MSG)] => ( is => 'ro', required => 1);

sub create_instance {
    return $self->package->new(message => $self->msg);
}

package FooBar::Object;
use Moose;

has msg => ( is => 'ro', required => 1);

sub Hi {
   my $self = shift;
   print "Hi, I'm a " . ref($self)  ." and I say [". $self->MSG()."]\n";
}

package Foo;
use Moose;
extends qw(FooBar::Object);

package Bar;
use Moose;
extends qw(FooBar::Object);


package main;
or my $line (<DATA>) {
   my ($case,$msg)=split(/[\n\r,]\s*/,$line);
   FooBar->new(SUBCLASS=>$case,MSG=>$msg)->create_instance->Hi
}

__DATA__
Foo, First Case
Bar, Second Case

Конечно, есть много других способов реализовать ту же концепцию в Moose. Не зная специфики проблемы вашей предметной области, трудно сказать, что что-то вроде MooseX :: Traits не было бы лучше:

package Foo;
use Moose;
with qw(MooseX::Traits);

package Bar;
use Moose;
with qw(MooseX::Traits);

package Messaging;
use Moose::Role;

has msg => ( is => 'ro', required => 1);

sub Hi {
   my $self = shift;
   print "Hi, I'm a " . ref($self)  ." and I say [". $self->MSG()."]\n";
}

package main;
use strict;
Foo->with_traits('Messaging')->new( msg => 'First Case')->Hi;

Это примерно то, что имел в виду другой плакат об использовании решения на основе ролей.

10
ответ дан 3 December 2019 в 03:36
поделиться

Вы можете просто сделать:

$case->new( MSG => $msg )->Hi();

Если это легче или лучше, решать вам.

5
ответ дан 3 December 2019 в 03:36
поделиться

Итак, объект уже создан, когда вызывается BUILD , поэтому я бы сказал

sub BUILD {
      my $self = shift;
      return bless $self, $self->SUBCLASS;
}

Вы всегда можете захотеть переключиться с модели на основе наследования. в ролевую модель, в которой вы создаете нужный объект (вместо передачи класса в фабричный класс), а затем применяете общую роль.

4
ответ дан 3 December 2019 в 03:36
поделиться

Просто используйте другой объект фабрики для создания объектов этого класса.

Проще, гибче, надежнее и т. Д.

my $ factory = Factory-> new (... заводские параметры ...);

my $ object = $ factory-> new_object (... различные параметры ...);

где new_object может анализировать параметры и принимать решения как по данным внутри $ factory , так и по данным из этих параметров.

Когда вы понимаете, что вам понадобятся созависимые объекты на следующем этапе ищите инверсию структуры управления.

3
ответ дан 3 December 2019 в 03:36
поделиться

Просто примечание к некоторым ответам:

Вызов bless в BUILD или где-либо еще за пределами внутреннего устройства MOP всегда неприемлем. (Если вам необходимо выполнить повторное восстановление, есть Class :: MOP :: Class-> rebless_instance !)

Я второй совет не позволять new возвращать что-либо, кроме экземпляра из __ ПАКЕТ __ . Если вам нужен метод, который создает экземпляр чего-то, назовите это как-нибудь еще. Пример:

class Message {
   method new_from_string(Str $msg){
       my ($foo, $bar, $baz) = ($msg =~ /<...>/); # blah blah blah
       my $class = "Message::${foo}::$baz";
       Class::MOP::load_class($class);
       return $class->new( bar => $msg );
   }
}

Затем, если вы хотите создать буквальное сообщение:

Message->new( whatever => 'you want' );

Если вы хотите проанализировать строку и вернуть правильный подкласс сообщения:

Message->new_from_string( 'OH::Hello!' );

Наконец, если нет смысла создавать экземпляр Message, то он не должен быть классом. Это должна быть роль.

Вы, конечно, можете управлять строительством с помощью другого объекта. Просто убедитесь, что этот другой объект отвечает только за понимание формата строки, например, а не за внутреннюю структуру сообщения:

class MessageString {
    has 'string' => ( initarg => 'string', reader => 'message_as_string' );

    method new_from_string(ClassName $class: Str $string) {
        return $class->new( string => $string );
    }

    method as_message_object {
        # <parse>
        return Message::Type->new( params => 'go here', ... );
    }
}

role Message { ... }
class Message::Type with Message { ... }

Теперь вас больше не беспокоит наличие какого-то «суперкласса», отвечающего за создание «подклассов», что, на мой взгляд, лучше дизайн. (Помните, что MessageString не имеет особой власти над классами, которые выполняют "Message". Это ключ здесь; он отвечает только за понимание строковых сообщений.)

В любом случае, теперь вы просто:

my $data =  <>; # Yup, I called it $data.  Sorry, Andy Lester.
my $parsed = MessageString->new_from_string( $data );
my $message = $parsed->as_message_object;
$message->interact_with

(Вы знаете "MVC" "? Это похоже.)

MessageString не имеет особой власти над классами, выполняющими «Message». Это ключ здесь; он отвечает только за понимание строковых сообщений.)

В любом случае, теперь вы просто:

my $data =  <>; # Yup, I called it $data.  Sorry, Andy Lester.
my $parsed = MessageString->new_from_string( $data );
my $message = $parsed->as_message_object;
$message->interact_with

(Вы знаете "MVC"? Это похоже.)

MessageString не имеет особой власти над классами, выполняющими «Message». Это ключ здесь; он отвечает только за понимание строковых сообщений.)

В любом случае, теперь вы просто:

my $data =  <>; # Yup, I called it $data.  Sorry, Andy Lester.
my $parsed = MessageString->new_from_string( $data );
my $message = $parsed->as_message_object;
$message->interact_with

(Вы знаете "MVC"? Это похоже.)

5
ответ дан 3 December 2019 в 03:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: