comparison lib/IMPL/Object/Factory.pm @ 407:c6e90e02dd17 ref20150831

renamed Lib->lib
author cin
date Fri, 04 Sep 2015 19:40:23 +0300
parents
children
comparison
equal deleted inserted replaced
406:f23fcb19d3c1 407:c6e90e02dd17
1 package IMPL::Object::Factory;
2 use strict;
3
4 use IMPL::Const qw(:prop);
5
6 use IMPL::declare {
7 base => [
8 'IMPL::Object' => undef,
9 'IMPL::Object::Serializable' => undef
10 ],
11 props => [
12 factory => PROP_RO,
13 parameters => PROP_RO,
14 method => PROP_RO
15 ]
16 };
17
18 # custom factory, overrides default
19 sub new {
20 my $self = shift;
21
22 return ref $self ? $self->CreateObject(@_) : $self->IMPL::Object::new(@_);
23 }
24
25 sub CTOR {
26 my ($this,$factory,$parameters,$method) = @_;
27
28 $this->factory($factory) or die new IMPL::InvalidArgumentException("The argument 'factory' is mandatory");
29 $this->parameters($parameters) if $parameters;
30 $this->method($method) if $method;
31 }
32
33 # override default restore method
34 sub restore {
35 my ($class,$data,$surrogate) = @_;
36
37 my %args = @$data;
38
39 if ($surrogate) {
40 $surrogate->self::CTOR($args{factory},$args{parameters},$args{method});
41 return $surrogate;
42 } else {
43 return $class->new($args{factory},$args{parameters},$args{method});
44 }
45 }
46
47 sub CreateObject {
48 my $this = shift;
49
50 if (my $method = $this->method) {
51 $this->factory->$method($this->MergeParameters(@_));
52 } else {
53 $this->factory->new($this->MergeParameters(@_));
54 }
55 }
56
57 sub MergeParameters {
58 my $this = shift;
59
60 $this->parameters ? (_as_list($this->parameters),@_) : @_;
61 }
62
63
64 sub _as_list {
65 ref $_[0] ?
66 (ref $_[0] eq 'HASH' ?
67 %{$_[0]}
68 :
69 (ref $_[0] eq 'ARRAY'?
70 @{$_[0]}
71 :
72 $_[0]
73 )
74 )
75 :
76 ($_[0]);
77 }
78
79
80 1;
81
82 __END__
83
84 =pod
85
86 =head1 SYNOPSIS
87
88 =begin code
89
90 my $factory = new IMPL::Object::Factory(
91 'MyApp::User',
92 {
93 isAdmin => 1
94 }
95 );
96
97 my $class = 'MyApp::User';
98
99 my $user;
100
101 $user = $class->new(name => 'nobody'); # will create object MyApp::User
102 # and pass parameters (name=>'nobody')
103
104 $user = $factory->new(name => 'root'); # will create object MyApp::User
105 # and pass paremeters (isAdmin => 1, name => 'root')
106
107 =end code
108
109 Или сериализованная форма в XML.
110
111 =begin code xml
112
113 <factory type="IMPL::Object::Factory">
114 <factory>MyApp::User</factory>,
115 <parameters type="HASH">
116 <isAdmin>1</isAdmin>
117 </parameters>
118 </factory>
119
120 =end code xml
121
122 =head1 DESCRIPTION
123
124 C<[Serializable]>
125
126 Класс, реализующий фабрику классов.
127
128 Фабрика классов это любой объект, который имеет метод C< new > вызов которого приводит к созданию нового
129 объекта. Например каждый класс сам явялется фабрикой, поскольку, если у него вызвать метод
130 C< new >, то будет создан объект. Полученные объекты, в силу механизмов языка Perl, также
131 являются фабриками, притом такимиже, что и класс.
132
133 Данный класс меняет поведение метода C< new > в зависимости от контекста вызова: статического
134 метода или метода объекта. При вызове метода C< new > у класса происходит создание объекта
135 фабрики с определенными параметрами. Далее объект-фабрика может быть использована для создания
136 объектов уже на основе параметров фабрики.
137
138 =head1 MEMBERS
139
140 =over
141
142 =item C< CTOR($factory,$parameters,$method) >
143
144 Создает новый экземпляр фабрики.
145
146 =over
147
148 =item C<$factory>
149
150 Либо имя класса, либо другая фабрика.
151
152 =item C<$parameters>
153
154 Ссылка на параметры для создания объектов, может быть ссылкой на хеш, массив и т.д.
155
156 Если является ссылкой на хеш, то при создании объектов данной фабрикой этот хеш
157 будет развернут в список и передан параметрами методу C<new>.
158
159 Если является ссылкой на массив, то при создании объектов данной фабрикой этот массив
160 будет передан в списк и передан параметрами методу C<new>.
161
162 Если является любым другим объектом или скаляром, то будет передан параметром методу
163 C<new> как есть.
164
165 =item C<$method>
166
167 Имя метода (или ссылка на процедуру), который будет вызван у C<$factory> при создании
168 текущей фабрикой нового объекта.
169
170 =back
171
172 =item C< [get] factory >
173
174 Свойство, содержащее фабрику для создание новых объектов текущей фабрикой. Чаще всего оно содержит
175 имя класса.
176
177 =item C< [get] parameters >
178
179 Свойство, содержит ссылку на параметры для создания объектов, при создании объекта эти параметры будут
180 развернуты в список и переданы оператору C< new > фабрике из свойства C< factory >, за ними будут
181 следовать параметры непосредственно текущей фабрики.
182
183 =item C<MergeParameters(@params)>
184
185 Метод смешивающий фиксированные параметры с параметрами переданными методу C<new(@params)>. По умолчанию
186 добавляет пареметры фабрики в конец к фиксированным параметрам. Для изменения этого поведения требуется
187 переопределить данный метод. Также этот метод можно переопределить для передачи параметров, значения
188 которых вычисляются.
189
190 =item C<new(@params)>
191
192 Создает новый объект, используя свйство C<factory> как фабрику и передавая туда параметры
193 из свойства C<parameters> и списка C<@params>. Ниже приведен упрощенный пример, как это происходит.
194
195 =begin code
196
197 sub new {
198 my ($this,@params) = @_;
199
200 my $method = $this->method || 'new';
201
202 return $this->factory->$method(_as_list($this->parameters), @params);
203 }
204
205 =end code
206
207 =back
208
209 =cut