SE450: Lecture 7
(Creational Patterns)
Midterm
Homework Solution
Martin's Principles
Creational Patterns
- Static Factory Method
- Singleton
- Prototype
- Factory
- Abstract Factory
- Factory Method
- Builder
You may keep your exams, but I won't be posting solutions,
just going over results in class
Homework files are here
Martin's principles are highlighted in the paper
Design Principles and Design Patterns at his website,
www.objectmentor.com. This
site is an excellent resource on OO programming, XP, and design techniques.
The Open/Closed Principle: Software entities (classes,
modules, etc) should be open for extension, but closed for
modification. Abstraction is the key to this principle. This
is possible through dynamic polymorphism.
The Liskov Substitution Principle: Derived classes must be
usable through the base class interface without the need for
the user to know the difference. This implies:
- if you write a subclass, you should never have to rewrite client code that
works with the superclass.
- If an instance of a class is expected,
an instance of the subclass should be substitutable.
- A subclass inherits the invariant (DBC), and can only strengthen it
- A precondition of an inherited method can be only weakened
- A postcondition can be only strengthened.
Violations of LSP are latent violations of OCP
The Dependency Inversion Principle: Details should depend
upon abstractions. Abstractions should not depend upon
details (concretions). Dependencies between classes
should target interfaces or abstract classes. This provides
flexibility to the design. This keeps you from depending
on volatile modules.
The Interface Segregation Principle: Many client specific
interfaces are better than one general purpose interface
The Reuse/Release Equivalency Principle: The granule of
reuse is the same as the granule of release. Only components
that are released through a tracking system can be
effectively reused.
The Common Closure Principle: Classes that change together,
belong together.
The Common Reuse Principle: Classes that aren't reused
together should not be grouped together.
The Acyclic Dependencies Principle: The dependency structure
for released components must be a directed acyclic
graph. There can be no cycles.
The Stable Dependencies Principle: Dependencies between
released categories must run in the direction of
stability. The dependee must be more stable than the
depender.
The Stable Abstractions Principle: The more stable a class
category is, the more it must consist of abstract classes. A
completely stable category should consist of nothing but
abstract classes.
|
Purpose |
Creational |
Structural |
Behavioral |
Scope |
Class |
Factory Method (107) |
Adapter (class) (139) |
Interpreter (243) Template Method (325) |
Object |
Abstract Factory (87)
Builder (97)
Prototype (117)
Singleton (127)
|
Adapter (object) (139)
Bridge (151)
Composite (163)
Decorator (175)
Facade (185)
Flyweight (195)
Proxy (207)
|
Chain of Responsibility (223)
Command (233)
Iterator (257)
Mediator (273)
Memento (283)
Observer (293)
State (305)
Strategy (315)
Visitor (331)
|
Normally, how do you create an instance of a class?
However, you can write your own method to instantiate a
class. This is not one of the GoF patterns, but is
documented in Joshua Bloch's Effective Java.
Benefits: Static Factory methods...
-
Have names
-
Aren't required to create a new object each time they
are invoked
-
They can return of object of any subtype of their return type.
Disadvantages:
-
Classes without public or protected constructors can't
be subclassed (this can be a blessing in disguise as it
forces programmers to use composition over inheritance)
-
Static Factory methods don't stand out from other static
methods. This is especially annoying when looking
through JavaDoc, since the constructors all get their
own section. Get around this by using conventions.
Convention:
-
valueOf
Returns an instance that has,
loosely speaking, the same value as its parameters.
Basically, it is a type conversion operator.
-
getInstance
Return an instance that is
described by its parameters but cannot be said to have
the same value. Used with Singletons (later). Used in
provider frameworks.
A good example of a static factory is in the Java APIs. For
example, in Boolean:
public static Boolean valueOf(boolean b) {
return (b ? Boolean.TRUE: Boolean.FALSE);
}
Somewhere in the Boolean class, there is code like this:
public static Boolean TRUE = new Boolean(true);
public static Boolean FALSE = new Boolean(false);
|
- Name - Singleton
- Intent - Ensure a class has only one instance,
and provide global access to it
- Problem -
-
There must be only one instance of a class, and it
must be accessible from a known point
-
The sole instance should be accessible by subclassing,
and clients should still be able to access the
instance without modifying code.
-
Solution - Allow only one instance of the object to
be created, and provide access to it through a static method.
- Participants and Collaborators
- Consequences
- Controlled access to sole instance
- Reduced name space
- Permits refinement of operations and representation
- the instance may be selected at run time, as an
example
- Permits a variable number of instances
- More flexible that just using static access (think
about method hiding...)
- Implementation
- Ensuring a unique instance
- Subclassing the Singleton class
- GoF Reference (127)
- Example files are
here
- Name -
- Intent - Specify the kinds of objects to create using a
prototypical instance, and create new objects by copying the prototype
- Problem -
- Classes are instantiated or specified at run time by dynamic loading
- You want to avoid building a class heirarchy of factories that
parallel the class heirarchy of products
- When instances of a class can only have a few combinations
of state.
-
Solution - Create a prototypical instance, and copy it (or clone
it) when you need new objects
- Participants and Collaborators
- Prototype
- ConcretePrototype (or just a Prototype)
- Client
- Consequences
- Hides the concrete product class - clients don't need to change
as much
- Need to be concerned about shallow vs. deep copy
- Allows you to return the type you want, instead of
Object
like the clone
method of Java
- Implementation
- Use a prototype manager
- Implement the "clone" operation
- Initialize the "clone"
- GoF Reference (117)
- Example files are
here
- Name - Factory
- Intent - Define an interface for creating objects but let
subclasses decide which class to instantiate and how.
- Problem -
- A system should be independent of how its products are
created.
-
Solution - Provide a
- Participants and Collaborators
- AbstractFactory
- ConcreteFactory
- Product
- ConcreteProduct
- Factory is similar to Abstract Factory and Factory Method, but
it is simpler. The pattern defines a Factory which makes the
Products, and that is the sole responsibility of the class.
We will discuss some of the differences as we come to the other two
patterns.
- Example files are
here
- Name - Abstract Factory
- A.K.A - Kit
- Intent - Provide a contract for creating families
of related or dependent objects without having to specify
their concrete classes
- Problem -
- You need to create products, but need the system to
be independent of how the products are created
- Your system needs to be configured with one of
multiple families of products
- A family of products needs to be used together, and
you need to enforce this constraint
- You need to hide the implementation of a library of
products by just revealing their interface.
-
Solution - Coordinate the creation of families of
objects. The rules of how to instantiate the products is
implemented in the factory, taking the responsibility from
the client.
- Participants and Collaborators
- AbstractFactory
- ConcreteFactory
- AbstractProduct
- ConcreteProduct
- Client
- Consequences
- Isolates concrete classes
- Makes exchanging product families easy
- Promotes consistency among products
- Supporting new kinds of products can be difficult
- Implementation
- Abstract Factories are often Singletons
- Often, a Factory Method is used to create the
product
- GoF Reference (87)
- Example files are
here
- The Abstract Factory is just used to create products. But unlike
the simple Factory, it defers the instantiation to subclasses. This
allows the products to be hidden from the client (just written to an
interface)
- Name - Factory Method
- A.K.A. - Virtual Constructor
- Intent - Define an interface for creating an
object, but let subclasses decide which class to
instantiate. Defers intantiation to subclasses.
- Problem -
- A class needs to instantiate a derivation of another
class, but doesn't know which one.
- A class wants its subclasses to specify the objects
it creates
-
Solution - A derived class makes the decision on
which class to instantiate and how to instatiate it.
- Participants and Collaborators
- Product
- ConcreteProduct
- Creator
- ConcreteCreator
- Consequences
- Clients might need to subclass the Creator class
just to make a particular ConcreteProduct
-
Factory methods eliminate the need to bind
application-specific classes into your code. You only
deal with generic Product interfaces, allowing
ConcreteProducts to be interchanged easily.
-
Provides hooks for subclasses
-
Connects parallel class heirarchies
- Implementation
- Two types: abstract Factory method, or a concrete
Factory method with default implementation
- Parameterized factory methods: can create multiple
product types from one method
- Naming conventions are a good idea
- GoF Reference (107)
- Example files are
here
- The Factory Method allows the creators to be more than just
creators for products, they might create a structure using the
products created from their factory methods.
- Name - Builder
- Intent - Separate the construction of a complex object
from its representation so that the same construction process
can create different representations. One class is responsible
for building products
- Problem -
- A class has a complicated internal structure, or order
dependent setters.
- You have too many constructors in your class to support too many
possible ways to construct it.
- The creation process uses resources or other objects that are
hard to create or obtain.
-
Solution - Use a Director class that is responsible for
building the parts of the product using different Builders.
- Participants and Collaborators
- Director
- Builder
- ConcreteBuilder
- Product
- Consequences
- The Builder can coordinate order constrained creation, providing
fallbacks when necessary
- The Builder can be a central point for resources needed
during creation (like database connections, files, etc). This
makes life much easier for clients of the Builder.
- Many times, builders are used to build composites
- GoF Reference (97)
- Example files are
here
Revised: 2003/2/16