annotate lib/IMPL/Object/Factory.pm @ 427:09e0086a82a7 ref20150831 tip

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