Design Patterns
239 pág.

Design Patterns


DisciplinaEngenharia de Software I4.656 materiais51.838 seguidores
Pré-visualização50 páginas
Each time the program reads an image, it needs to create a reader of the appropriate type based on some information
in the file. This logic can be encapsulated in a factory method:
public class ImageReaderFactory {
 public static ImageReader imageReaderFactoryMethod(InputStream is) {
 ImageReader product = null;
 int imageType = determineImageType(is);
 switch (imageType) {
 case ImageReaderFactory.GIF:
 product = new GifReader(is);
 case ImageReaderFactory.JPEG:
 product = new JpegReader(is);
 //...
 }
 return product;
 }
}
Factory method pattern 35
Example implementations
Java
A maze game may be played in two modes, one with regular rooms that are only connected with adjacent rooms, and
one with magic rooms that allow players to be transported at random (this Java example is similar to one in the book
Design Patterns). The regular game mode could use this template method:
public class MazeGame {
 public MazeGame() {
 Room room1 = makeRoom();
 Room room2 = makeRoom();
 room1.connect(room2);
 this.addRoom(room1);
 this.addRoom(room2);
 }
 protected Room makeRoom() {
 return new OrdinaryRoom();
 }
}
In the above snippet, the MazeGame constructor is a template method that makes some common logic. It refers to
the makeRoom factory method that encapsulates the creation of rooms such that other rooms can be used in a
subclass. To implement the other game mode that has magic rooms, it suffices to override the makeRoom method:
public class MagicMazeGame extends MazeGame {
 @Override
 protected Room makeRoom() {
 return new MagicRoom();
 }
}
PHP
Another example in PHP follows:
class Factory
{
 public static function build($type)
 {
 $class = 'Format' . $type;
 if (!class_exists($class)) {
 throw new Exception('Missing format class.');
 }
 return new $class;
 }
}
class FormatString {}
class FormatNumber {}
Factory method pattern 36
try {
 $string = Factory::build('String');
}
catch (Exception $e) {
 echo $e->getMessage();
}
try {
 $number = Factory::build('Number');
}
catch (Exception $e) {
 echo $e->getMessage();
}
Limitations
There are three limitations associated with the use of the factory method. The first relates to refactoring existing
code; the other two relate to extending a class.
\u2022\u2022 The first limitation is that refactoring an existing class to use factories breaks existing clients. For example, if
class Complex was a standard class, it might have numerous clients with code like:
Complex c = new Complex(-1, 0);
Once we realize that two different factories are needed, we change the class (to the code shown earlier). But
since the constructor is now private, the existing client code no longer compiles.
\u2022\u2022 The second limitation is that, since the pattern relies on using a private constructor, the class cannot be extended.
Any subclass must invoke the inherited constructor, but this cannot be done if that constructor is private.
\u2022 The third limitation is that, if we do extend the class (e.g., by making the constructor protected\u2014this is risky but
feasible), the subclass must provide its own re-implementation of all factory methods with exactly the same
signatures. For example, if class StrangeComplex extends Complex, then unless StrangeComplex
provides its own version of all factory methods, the call
StrangeComplex.fromPolar(1, pi);
will yield an instance of Complex (the superclass) rather than the expected instance of the subclass. The reflection
features of some languages can obviate this issue.
All three problems could be alleviated by altering the underlying programming language to make factories first-class
class members (see also Virtual class).[3]
Factory method pattern 37
Uses
\u2022 In ADO.NET, IDbCommand.CreateParameter [4] is an example of the use of factory method to connect parallel
class hierarchies.
\u2022 In Qt, QMainWindow::createPopupMenu [5] is a factory method declared in a framework that can be overridden
in application code.
\u2022 In Java, several factories are used in the javax.xml.parsers [6] package. e.g.
javax.xml.parsers.DocumentBuilderFactory or javax.xml.parsers.SAXParserFactory.
References
[1][1] Gang Of Four
[2] Feathers, Michael (October 2004), Working Effectively with Legacy Code, Upper Saddle River, NJ: Prentice Hall Professional Technical
Reference, ISBN 978-0-13-117705-5
[3] Agerbo, Aino; Agerbo, Cornils (1998). "How to preserve the benefits of design patterns". Conference on Object Oriented Programming
Systems Languages and Applications (Vancouver, British Columbia, Canada: ACM): 134\u2013143. ISBN 1-58113-005-8.
[4] http:/ / msdn2. microsoft. com/ en-us/ library/ system. data. idbcommand. createparameter. aspx
[5] http:/ / doc. trolltech. com/ 4. 0/ qmainwindow. html#createPopupMenu
[6] http:/ / download. oracle. com/ javase/ 1. 5. 0/ docs/ api/ javax/ xml/ parsers/ package-summary. html
\u2022 Fowler, Martin; Kent Beck, John Brant, William Opdyke, and Don Roberts (June 1999). Refactoring: Improving
the Design of Existing Code. Addison-Wesley. ISBN 0-201-48567-2.
\u2022 Gamma, Erich; Helm, Richard; Johnson, Ralph; Vlissides, John (1994). Design Patterns: Elements of Reusable
Object-Oriented Software. Addison-Wesley. ISBN 0-201-63361-2.
\u2022 Cox, Brad J.; (1986). Object-oriented programming: an evolutionary approach. Addison-Wesley.
ISBN 978-0-201-10393-9.
\u2022 Cohen, Tal; Gil, Joseph (2007). "Better Construction with Factories" (http:/ / tal. forum2. org/ static/ cv/
Factories. pdf) (PDF). Journal of Object Technology (Bertrand Meyer). Retrieved 2007-03-12.
External links
\u2022 Factory method in UML and in LePUS3 (http:/ / www. lepus. org. uk/ ref/ companion/ FactoryMethod. xml) (a
Design Description Language)
\u2022 Consider static factory methods (http:/ / drdobbs. com/ java/ 208403883) by Joshua Bloch
Lazy initialization 38
Lazy initialization
In computer programming, lazy initialization is the tactic of delaying the creation of an object, the calculation of a
value, or some other expensive process until the first time it is needed.
This is typically accomplished by maintaining a flag indicating whether the process has taken place. Each time the
desired object is summoned, the flag is tested. If it is ready, it is returned. If not, it is initialized on the spot.
See lazy evaluation for a general treatment of this idea. In heavily imperative languages this pattern carries hidden
dangers, as does any programming habit that relies on shared state.
The "lazy factory"
In a software design pattern view, lazy initialization is often used together with a factory method pattern. This
combines three ideas:
\u2022 using a factory method to get instances of a class (factory method pattern)
\u2022 storing the instances in a map, so you get the same instance the next time you ask for an instance with same
parameter (Multiton pattern, similar to the singleton pattern)
\u2022\u2022 using lazy initialization to instantiate the object the first time it is requested (lazy initialization pattern).
Examples
Actionscript 3
The following is an example of a class with Lazy initialization implemented in Actionscript:
package examples.lazyinstantiation
{
 public class Fruit 
 {
 private var _typeName:String;
 private static var instancesByTypeName:Dictionary = new 
Dictionary();
 
 public function Fruit(typeName:String):void
 {
 this._typeName = typeName;
 }
 
 public function get typeName():String