forked from LibertyEiffel/Liberty
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PATTERNS.txt
203 lines (150 loc) · 4.29 KB
/
PATTERNS.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
------------------------------------------------------------------------------
Some patterns I find useful when developing in Liberty Eiffel.
These patterns nicely complement the standard GoF patterns.
------------------------------------------------------------------------------
Typed Derivation
================
Pattern:
--------
deferred class NON_TYPED
...
end
class TYPED[E_]
inherit
NON_TYPED
...
end
Usage:
------
When you need to keep mixed up data whose type is not known in advance.
The non_typed base class is used to present a common non-typed
interface and move the data around, the typed class is used to access
the data itself.
This pattern is really useful to enforce strong typing.
See also:
---------
A companion pattern is the Agent-based Generics Visitor (see below).
Examples:
---------
* SmartEiffel's INTERNALS
* Liberty's interpreter: objects, builtins
------------------------------------------------------------------------------
Agent-based Visitor
===================
(the non-generics one)
Pattern:
--------
class ITEM
feature {ANY}
accept (v: VISITOR) do visitor.call([v, Current]) end
feature {}
visitor: PROCEDURE[TUPLE[VISITOR, ITEM]]
...
end
class FACTORY
feature {ANY}
new_item_1: SOMETHING
do
create Result.make(agent {VISITOR}.visit_1)
end
new_item_2: SOMETHING
do
create Result.make(agent {VISITOR}.visit_2)
end
...
end
deferred class VISITOR
feature {ANY}
visit_1 (i: ITEM) is deferred end
visit_2 (i: ITEM) is deferred end
...
end
Usage:
------
Some objects share a common base type, but we need to distinguish some
instances with a special role. For some reason we want the objects to
share the same runtime type.
This kind of visitor helps differentiating instances. The agent is
registered at the creation of ITEM and depends on the object itself.
These objects should be immutable (at least conceptually; their
creation cycle may be complex).
Note: usually the "agent {VISITOR}.visit_xx" is encapsulated in a once
feature, to avoid the creation of too many objects. That's one reason
why the visitor itself is given as target of the call. The other
reason is of course to allow visitor polymorphism.
The deferred visitor is defined as usual.
See also:
---------
Factory, to create the objects and give them an agent.
Examples:
---------
* Liberty's actual type visitor, an agent is given at creation time
that depends on the actual instance of LIBERTY_ACTUAL_TYPE.
* Liberty's "feature accelerator" is also the same pattern.
* In fact the whole Liberty interpreter is built as an application of
this pattern.
------------------------------------------------------------------------------
Agent-based Generics Visitor
============================
Pattern:
--------
deferred class ITEM
feature {ANY}
accept (v: VISITOR) deferred end
end
class TYPED_ITEM[E_]
inherit
ITEM
feature {ANY}
item: E_
accept (v: VISITOR) do visitor.call([v, Current]) end
feature {}
visitor: PROCEDURE[TUPLE[VISITOR, E_]]
...
end
class FACTORY
feature {ANY}
new_item_a (a: A): ITEM
do
create {TYPED_ITEM[A]} Result.make(a, agent {VISITOR}.visit_a)
end
new_item_b (b: B): ITEM
do
create {TYPED_ITEM[B]} Result.make(b, agent {VISITOR}.visit_b)
end
...
end
deferred class VISITOR
feature {ANY}
visit_a (i: TYPED_ITEM[A]) deferred end
visit_b (i: TYPED_ITEM[B]) deferred end
...
end
Usage:
------
A simple application of the Agent-based Visitor to Typed Derivation.
That kind of visitor helps getting access to the data of a Typed
Derivation. The agent is registered at the creation of TYPED_ITEM[E_]
and depends on E_ itself.
See also:
---------
Factory, to create typed objects and give them an agent.
------------------------------------------------------------------------------
Acyclic Visitor
===============
http://www.objectmentor.com/resources/articles/acv.pdf
------------------------------------------------------------------------------
Root class creation
===================
The pattern I usually use is a creation procedure that is not exported
either by 'feature' or by 'create':
class ROOT
create {}
make
feature {}
make
do
-- The program starts here...
end
end
------------------------------------------------------------------------------