| 64 | 1 package IMPL::Object::Factory; | 
|  | 2 use strict; | 
|  | 3 | 
|  | 4 use base qw(IMPL::Object IMPL::Object::Serializable); | 
|  | 5 | 
|  | 6 use IMPL::Class::Property; | 
|  | 7 | 
|  | 8 BEGIN { | 
|  | 9 	public property factory => prop_get | owner_set; | 
|  | 10 	public property parameters => prop_get | owner_set; | 
|  | 11 } | 
|  | 12 | 
|  | 13 # custom factory, overrides default | 
|  | 14 sub new { | 
|  | 15 	my $self = shift; | 
|  | 16 | 
|  | 17 	return ref $self ? $self->CreateObject(@_) : $self->SUPER::new(@_); | 
|  | 18 } | 
|  | 19 | 
|  | 20 sub CTOR { | 
|  | 21 	my ($this,$factory,$parameters) = @_; | 
|  | 22 | 
|  | 23 	$this->factory($factory) or die new IMPL::InvalidArgumentException("The argument 'factory' is mandatory"); | 
|  | 24 	$this->parameters($parameters) if $parameters; | 
|  | 25 } | 
|  | 26 | 
|  | 27 # override default restore method | 
|  | 28 sub restore { | 
|  | 29 	my ($class,$data,$surrogate) = @_; | 
|  | 30 | 
|  | 31 	my %args = @$data; | 
|  | 32 | 
|  | 33 	if ($surrogate) { | 
|  | 34 		$surrogate->callCTOR($args{factory},$args{parameters}); | 
|  | 35 		return $surrogate; | 
|  | 36 	} else { | 
|  | 37 		return $class->new($args{factory},$args{parameters}); | 
|  | 38 	} | 
|  | 39 } | 
|  | 40 | 
|  | 41 sub CreateObject { | 
|  | 42 	my $this = shift; | 
|  | 43 | 
|  | 44 	return $this->factory->new($this->parameters ? (_as_list($this->parameters),@_) : @_); | 
|  | 45 } | 
|  | 46 | 
|  | 47 sub _as_list { | 
|  | 48 	ref $_[0] ? | 
|  | 49 		(ref $_[0] eq 'HASH' ? | 
|  | 50 			%{$_[0]} | 
|  | 51 			: | 
|  | 52 			(ref $_[0] eq 'ARRAY'? | 
|  | 53 				@{$_[0]} | 
|  | 54 				: | 
|  | 55 				$_[0] | 
|  | 56 			) | 
|  | 57 		) | 
|  | 58 		: | 
|  | 59 		($_[0]); | 
|  | 60 } | 
|  | 61 | 
|  | 62 | 
|  | 63 1; | 
|  | 64 | 
|  | 65 __END__ | 
|  | 66 | 
|  | 67 =pod | 
|  | 68 | 
|  | 69 =head1 SYNOPSIS | 
|  | 70 | 
|  | 71 =begin code | 
|  | 72 | 
|  | 73 sub ProcessItems { | 
|  | 74 	my ($factory,$items); | 
|  | 75 | 
|  | 76 	return map $factory->new($_), @$items; | 
|  | 77 } | 
|  | 78 | 
|  | 79 my @users = ProcessItems('MyApp::User',$db->selectUsers); | 
|  | 80 | 
|  | 81 my $factory = new IMPL::Object::Factory( | 
|  | 82 	'MyApp::User', | 
|  | 83 	{ | 
|  | 84 		isAdmin => 1 | 
|  | 85 	} | 
|  | 86 ); | 
|  | 87 | 
|  | 88 =end code | 
|  | 89 | 
|  | 90 my @admins = ProcessItems($factory,$db->selectAdmins); | 
|  | 91 | 
|  | 92 | 
|  | 93 =head1 DESCRIPTION | 
|  | 94 | 
|  | 95 Класс, реализующий фабрику классов. | 
|  | 96 | 
|  | 97 Фабрика классов это любой объект, который имеет метод C< new > вызов которого приводит к созданию нового | 
|  | 98 объекта. Например каждый класс сам явялется фабрикой, поскольку, если у него вызвать метод | 
|  | 99 C< new >, то будет создан объект. Полученные объекты, в силу механизмов языка Perl, также | 
|  | 100 являются фабриками, притом такимиже, что и класс. | 
|  | 101 | 
|  | 102 Данный класс меняет поведение метода C< new > в зависимости от контекста вызова: статического | 
|  | 103 метода или метода объекта. При вызове метода C< new > у класса происходит создание объекта | 
|  | 104 фабрики с определенными параметрами. Далее объект-фабрика может быть использована для создания | 
|  | 105 объектов уже на основе параметров фабрики. | 
|  | 106 | 
|  | 107 =head1 MEMBERS | 
|  | 108 | 
|  | 109 =over | 
|  | 110 | 
|  | 111 =item C< factory > | 
|  | 112 | 
|  | 113 Свойство, содержащее фабрику для создание новых объектов текущей фабрикой. Чаще всего оно содержит | 
|  | 114 имя класса. | 
|  | 115 | 
|  | 116 =item C< parameters > | 
|  | 117 | 
|  | 118 Свойство, содержит ссылку на параметры для создания объектов, при создании объекта эти параметры будут | 
|  | 119 развернуты в список и переданы оператору C< new > фабрике из свойства C< factory >, за ними будут | 
|  | 120 следовать параметры непосредственно текущей фабрики. | 
|  | 121 | 
|  | 122 =back | 
|  | 123 | 
|  | 124 =cut |