Factory Abstract Factory Creational Patterns1 Making Objects The
Factory, Abstract Factory Creational Patterns(1) Making Objects The Smart Way
1 What is a Design Pattern? “Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice. ” [1] [Christopher Alexander] Design patterns capture the best practices of experienced object-oriented software developers. Design patterns are solutions to general software development problems.
2 Pattern’s Elements – Pattern Name n In general, a pattern has four essential elements. n The pattern name The problem The solution The consequences n n n
3 The Pattern Name n The pattern name is a handle we can use to describe a design problem, its solutions, and consequences in a word or two. ¨ Naming a pattern immediately increases the design vocabulary. It lets us design at a higher level of abstraction. ¨ Having a vocabulary for patterns lets us talk about them. ¨ It makes it easier to think about designs and to communicate them and their trade-offs to others.
4 The Problem n The problem describes when to apply the pattern. n ¨ It explains the problem and its context. ¨ It might describe specific design problems such as how to represent algorithms as objects. ¨ It might describe class or object structures that are symptomatic of an inflexible design. ¨ Sometimes the problem will include a list of conditions that must be met before it makes sense to apply the pattern.
5 The Solution n The solution describes the elements that make up the design, their relationships, responsibilities, and collaborations. ¨ The solution doesn't describe a particular concrete design or implementation, because a pattern is like a template that can be applied in many different situations. ¨ Instead, the pattern provides an abstract description of a design problem and how a general arrangement of elements (classes and objects in our case) solves it.
6 The Consequences n The consequences are the results and trade-offs of applying the pattern. ¨ The consequences for software often concern space and time trade-offs. ¨ They may address language and implementation issues as well. ¨ Since reuse is often a factor in object-oriented design, the consequences of a pattern include its impact on a system's flexibility, extensibility, or portability. ¨ Listing these consequences explicitly helps you understand evaluate them
7 Design Patterns Types n Erich Gamma, Richard Helm, Ralph Johnson and John Vlisides in their Design Patterns book define 23 design patterns divided into three types: Creational patterns are ones that create objects for you, rather than having you instantiate objects directly. This gives your program more flexibility in deciding which objects need to be created for a given case. ¨ Structural patterns help you compose groups of objects into larger structures, such as complex user interfaces or accounting data. ¨ Behavioral patterns help you define the communication between objects in your system and how the flow is controlled in a complex program. ¨
8 Why Use Patterns with Java? n n They have been proven. Patterns reflect the experience, knowledge and insights of developers who have successfully used these patterns in their own work. They are reusable. Patterns provide a readymade solution that can be adapted to different problems as necessary. They are expressive. Patterns provide a common vocabulary of solutions that can express large solutions succinctly. J 2 EE provides built in patterns.
9 What are creational patterns? n n n Design patterns that deal with object creation mechanisms, trying to create objects in a manner suitable to the situation Make a system independent of the way in which objects are created, composed and represented Recurring themes: ¨ Encapsulate knowledge about which concrete classes the system uses (so we can change them easily later) ¨ Hide how instances of these classes are created and put together (so we can change it easily later)
10 Creational Patterns and Java I § § The creational patterns deal with the best way to create instances of objects. In Java, the simplest way to create an instance of an object is by using the new operator. Fred = new Fred(); //instance of Fred class This amounts to hard coding, depending on how you create the object within your program. In many cases, the exact nature of the object that is created could vary with the needs of the program and abstracting the creation process into a special “creator” class can make your program more flexible and general.
11 Creational Patterns and Java II § § § The Factory Pattern provides a simple decision making class that returns one of several possible subclasses of an abstract base class depending on the data that are provided. The Abstract Factory Pattern provides an interface to create and return one of several families of related objects. The Builder Pattern separates the construction of a complex object from its representation. The Prototype Pattern starts with an initialized and instantiated class and copies or clones it to make new instances rather than creating new instances. The Singleton Pattern is a class of which there can be no more than one instance. It provides a single global point of access to that instance.
12 Benefits of creational patterns n n n Creational patterns let you program to an interface defined by an abstract class That lets you configure a system with “product” objects that vary widely in structure and functionality Example: GUI systems ¨ Inter. Views GUI class library ¨ Multiple look-and-feels ¨ Abstract Factories for different screen components
13 Benefits of creational patterns n n n Generic instantiation – Objects are instantiated without having to identify a specific class type in client code (Abstract Factory, Factory) Simplicity – Make instantiation easier: callers do not have to write long complex code to instantiate and set up an object (Builder, Prototype pattern) Creation constraints – Creational patterns can put bounds on who can create objects, how they are created, and when they are created
14 The Factory Pattern The Factory pattern returns an instance of one of several possible classes depending on the data provided to it. § § § Here, x is a base class and classes xy and xz are derived from it. The Factory is a class that decides which of these subclasses to return depending on the arguments you give it. The get. Class() method passes in some value abc, and returns some instance of the class x. Which one it returns doesn't matter to the programmer since they all have the same methods, but different implementations.
15 The Factory Pattern base class § § Let's consider a simple case where we could use a Factory class. Suppose we have an entry form and we want to allow the user to enter his name either as “firstname lastname” or as “lastname, firstname”. Let’s make the assumption that we will always be able to decide the name order by whethere is a comma between the last and first name. class Namer { //a class to take a string apart into two names protected String last; //store last name here protected String first; //store first name here public String get. First() { return first; //return first name } public String get. Last() { return last; //return last name } }
16 The Factory Pattern: The First Derived Class In the First class, we assume that everything before the last space is part of the first name. class First extends Namer { public First(String s) { int i = s. last. Index. Of(" "); //find separating space if (i > 0) { first = s. substring(0, i). trim(); //left = first name last =s. substring(i+1). trim(); //right = last name } else { first = “” // put all in last name last = s; // if no space } } }
17 The Factory Pattern: The Second Derived Class In the Last. First class, we assume that a comma delimits the last name. class Last. First extends Namer { //split last, first public Last. First(String s) { int i = s. index. Of(", "); //find comma if (i > 0) { last = s. substring(0, i). trim(); //left= last name first = s. substring(i + 1). trim(); //right= first name } else { last = s; // put all in last name first = ""; // if no comma } } }
18 The Factory Pattern: Building the Factory The Factory class is relatively simple. We just test for the existence of a comma and then return an instance of one class or the other. class Name. Factory { //returns an instance of Last. First or First //depending on whether a comma is found public Namer get. Namer(String entry) { int i = entry. index. Of(", "); //comma determines name order if (i>0) return new Last. First(entry); //return one class else return new First(entry); //or the other } }
19 The Factory Pattern: Using the Factory Name. Factory nfactory = new Name. Factory(); String s. First. Name, s. Last. Name; …. private void compute. Name() { //send the text to the factory and get a class back namer = nfactory. get. Namer(entry. Field. get. Text()); //compute the first and last names using the returned class s. First. Name = namer. get. First(); s. Last. Name = namer. get. Last(); }
20 When to Use a Factory Pattern You should consider using a Factory pattern when: § A class can’t anticipate which kind of class of objects it must create. § A class uses its subclasses to specify which objects it creates. § You want to localize the knowledge of which class gets created. There are several similar variations on the factory pattern to recognize: § The base class is abstract and the pattern must return a complete working class. § The base class contains default methods and is only subclassed for cases where the default methods are insufficient. § Parameters are passed to the factory telling it which of several class types to return. In this case the classes may share the same method names but may do something quite different.
21 (UML Class Diagram review) 0 or more (many) “part of” Relationship between objects of the same class (many departments have common name) “inheritance” Spec. kind of office 1 or more Couples logical and physical part “uses”
22 Factory n n n creating objects without specifying the exact class of object that will be created Define an interface for creating an object, but let the classes that implement the interface decide which class to instantiate: defer instantiation to subclasses Solution: define a separate method for creating the objects, whose subclasses can then override to specify the derived type of product that will be created
23 Factory method n n An increasingly popular definition of factory method is: a static method of a class that returns an object of that class' type. unlike a constructor, ¨ the actual object it returns might be an instance of a subclass. ¨ an existing object might be reused, instead of a new object created. ¨ factory methods can have different and more descriptive names (e. g. Color. make_RGB_color(float red, float green, float blue) and Color. make_HSB_color(float hue, float saturation, float brightness)
24 Factory checklist 1. 2. 3. 4. If you have an inheritance hierarchy that exercises polymorphism, consider adding a polymorphic creation capability by defining a static factory method in the base class. Design the arguments to the factory method. What qualities or characteristics are necessary and sufficient to identify the correct derived class to instantiate? Consider designing an internal "object pool" that will allow objects to be reused instead of created from scratch. (can return the same instance / recycle) Consider making all constructors private or protected. (encapsulate creation: request an object without coupling to creation)
25 The Abstract Factory Pattern: How does it Work? The Abstract Factory pattern is one level of abstraction higher than the factory pattern. It provide an interface for creating families of related objects, without specifying concrete classes. The pattern returns one of several related classes, each of which can return several different objects on request. In other words, the Abstract Factory is a factory object that returns one of several factories. One classic application of the abstract factory is the case where your system needs to support multiple “look-and-feel” user interfaces, such as Windows, Motif or Macintosh: § You tell the factory that you want your program to look like Windows and it returns a GUI factory which returns Windows-like objects. § When you request specific objects such as buttons, check boxes and windows, the GUI factory returns Windows instances of these visual interface components.
Abstract Factory n Intent ¨ Provide an interface for creating families of related or dependent objects without specifying their concrete classes n Analogous to a pasta maker Your code is the pasta maker Different disks create different pasta shapes: these are the factories All disks have certain properties in common so that they will work with the pasta maker All pastas have certain characteristics in common that are inherited from the generic “Pasta” object 26
27 Abstract Factory: Participants n Abstract. Factory Declares an interface for operations that create abstract products n Concrete. Factory Implements the operations to create concrete product objects: usually instantiated as a Singleton n Abstract. Product Declares an interface for a type of product object; Concrete Factories produce the concrete products n Concrete. Product Defines a product object to be created by the corresponding concrete factory
28 The GUI example
29 A Garden Maker Factory Suppose you are writing a program to plan the layout of gardens. These could be annual gardens, vegetable gardens or perennial gardens. However, no matter which kind of garden you are planning, you want to ask the same questions: § What are good border plants? § What are good center plants? § What plants do well in partial shade? We want a base Garden class that can answer these questions: public abstract class Garden { public abstract Plant get. Center(); public abstract Plant get. Border(); public abstract Plant get. Shade(); }
30 The Plant class simply contains and returns the plant name: public class Plant { String name; public Plant(String pname) { name = pname; //save name } public String get. Name() { return name; } }
31 A Garden class simply returns one kind of each plant. So, for example, for the vegetable garden we simply write: // factory public class Vegie. Garden extends Garden { public Plant get. Shade() { return new Plant("Broccoli"); } public Plant get. Center() { return new Plant("Corn"); } public Plant get. Border() { return new Plant("Peas"); } }
32 A Garden Maker Class – The Abstract Factory We create a series of Garden classes - Vegie. Garden, Perennial. Garden, and Annual. Garden, each of which returns one of several Plant objects. Next, we construct our abstract factory to return an object instantiated from one of these Garden classes and based on the string it is given as an argument: class Garden. Maker { //Abstract Factory which returns one of three gardens private Garden gd; public Garden get. Garden(String gtype) { gd = new Vegie. Garden(); //default if(gtype. equals("Perennial")) gd = new Perennial. Garden(); if(gtype. equals("Annual")) gd = new Annual. Garden(); return gd; } }
33 Consequences of Abstract Factory § § § One of the main purposes of the Abstract Factory is that it isolates the concrete classes that are generated. The actual class names of these classes are hidden in the factory and need not be known at the client level at all. Because of the isolation of classes, you can change or interchange these product class families freely. Since you generate only one kind of concrete class, this system keeps you for inadvertently using classes from different families of products. While all of the classes that the Abstract Factory generates have the same base class, there is nothing to prevent some derived classes from having additional methods that differ from the methods of other classes.
34 Abstract Factory: Applicability n Use Abstract Factory when: ¨A system should be independent of how its products are created, composed, and represented ¨ A system should be configured with one of multiple families of products ¨ You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations
Review: Abstract Factory Consequences n Good: ¨ Isolates n All manipulation on client-side done through abstract interfaces ¨ Makes n concrete classes exchanging product families easy Just change the Concrete. Factory instance ¨ Enforces n consistency among products Implementation: usually should be a Singleton 35
Review: Abstract Factory Consequences n Bad ¨ Adding a new product requires extending the abstract interface which implies that all of its derived concrete classes also must change. The following changes needs to be taken care of: n n n New abstract product class is added New product implementation is added Abstract factory interface is extended Derived concrete factories must implement the extensions Client has to be extended to use the new product Solution: add a param to the method that creates objects, then a single asbtract factory method Make(Object. Type) is enough 36
37 Abstract factory checklist 1. 2. 3. 4. 5. Decide if "platform independence" and creation services are the current source of pain. Map out a matrix of "platforms" versus "products". Define a factory interface that consists of a factory method per product. Define a factory derived class for each platform that encapsulates all references to the new operator. The client should retire all references to new, and use the factory methods to create the product objects.
38 Conclusions n Abstract Factory: ¨ Lets you choose what family of products to create at runtime ¨ Isolates the implementation from clients, since clients only use the interfaces ¨ Makes exchanging product families simple n n A full example – abstract factory for addresses: http: //www. javabeat. net/2008/08/abstract-factory -pattern Reference (hebrew) ¨ http: //vlib. eitan. ac. il/dp/abstract_factory. html
- Slides: 39