Mercurial > pub > Impl
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 |