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