Design Patterns and Frameworks_ 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM)
Design Patterns and Frameworks_ 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM)
This unit explores a number of standard design patterns representing proven solutions to
recurring software engineering problems. The unit also considers frameworks that offer
an out-of-the-box implementation and dictate the architecture of an application.
creational
concerned with object creation
structural
concerned with static composition of classes and objects into a program structure
behavioural
concerned with management of complex behaviour of objects and classes
Examples of some of these patterns and their typical use will be discussed in the
following sessions.
supports reuse;
Design Patterns are descriptions of problems and the essence of their solutions, and
reflect accumulated wisdom and experience of software designers. Patterns capture
these proven solutions for reuse in software design. In effect, patterns facilitate
experience and design reuse as opposed to code reuse (though they often do this, too).
Patterns not only describe how software is structured, but also how classes and objects
interact, especially at run time. Taking these interactions and their consequences
explicitly into account leads to more flexible and reusable software.
As well as being tested solutions to common problems, patterns can be used as a shared
vocabulary for understanding and discussing object-oriented software design. This
enables communication among design and development teams in terms of the patterns to
use.
The art and science of design patterns was introduced to the world of software
engineering by the seminal book Design Patterns: Elements of Reusable Object-Oriented
Software by Gamma, Helm, Johnson, and Vlissides, commonly referred to as the "Gang
of Four" (GoF). The book introduced a catalogue of 23 patterns for use in object-oriented
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 2 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
software projects.
Other, more recent catalogues extend this repertoire, and most importantly, extend
coverage to more specialized types of problems, e.g. problems involving concurrency or
patterns for multi-tier applications.
The Gang of Four define a Design Pattern as, "a solution to a problem in a context"; the
words in italics being the essence of a pattern. The other essential elements of a pattern
are its name and classification, its intent, and a statement of the consequences of
applying the pattern.
The GoF book structures 23 classic design patterns representing a set of qualities,
characteristics, and constraints, into three distinct categories based on their purpose:
Creational
These patterns control object creation, initialisation, and class selection. They include:
Factory (Factory Method and Abstract Factory): lets a class defer its instantiation to
subclasses.
Other patterns in this category are Builder and Prototype. These are not covered in this
unit as they are less commonly applied in Java.
Structural
The patterns in this category organise relationships between classes and objects,
providing guidelines for combining and using related objects. They include:
Other patterns in this category are Adapter, Bridge, Facade, Flyweight and Proxy.
Behavioural
These patterns control communication, messaging, and interaction between objects.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 3 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
Patterns are often classified by a second criterion, their scope, based on their applicability
to classes and objects:
Class Patterns describe how relationships between classes and subclasses are
defined through inheritance. Relationships in class patterns are static and established
at compile time. The patterns in this category are Template Method and Factory
Method (others being, Adapter and Interpreter).
Object Patterns describe relationships between objects and are primarily defined by
composition. Relationships in object patterns are typically created at runtime and are
more dynamic and flexible. The patterns in this category are Singleton, Composite,
Decorator, Iterator, Observer and Strategy (others being, Facade, Proxy, Abstract
Factory, Visitor, etc).
Since designs must be eventually implemented in code, Design Patterns also provide
sample programming language (C++ or Java) code to illustrate the implementation.
This unit aims to familiarise you with some of these original GoF patterns and help you to
see how these patterns work and how architectural design choices are made on their
basis. The unit covers basic Java implementation of patterns. This is accompanied by
their visualisation using class diagrams depicting the behaviours and relationships among
classes.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 4 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
classes.
You should aim to understand the intent of each pattern to appreciate when the pattern
may be applied and the results and trade-offs of applying it. Do bear in mind that patterns
are not concrete design descriptions, but a template for a design solution that can be
instantiated in different ways to suit the needs of specific applications. Sometimes the
patterns can be used directly, but sometimes they provide sources of inspiration.
Creational patterns provide an alternative for the standard object creation procedure in
Java using the new operator. The issue with concrete class instantiation (an
implementation as opposed to an interface) using new is that it often leads to coupling or
dependency problems, making the code inflexible. These patterns provide a way to
decouple a client from the objects it needs to instantiate. We will see an example of this
in the Factory pattern.
1. Singleton
2. Factory
The intent of the Singleton pattern as defined in Design Patterns is to, "ensure a class
has only one instance, and provides a [single,] global point of access to it".
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 5 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
has only one instance, and provides a [single,] global point of access to it".
The singleton pattern is based on a single class that holds a reference to the only
instance of itself while controlling its creation and its access via a single getter method.
This pattern is useful when only one object is needed to coordinate a set of actions.
This is a general class diagram for Singleton, showing a private static property of a
Singleton object as well as a public method (Instance()) that returns the property. This is
the core of what makes a Singleton. The other properties and methods represent
additional operations that may be allowed on the class. Clients access any instance of a
Singleton only through the Instance method.
However, this can cause a problem when we wish to use the Logger class from multiple
other classes in our program. Although we can pass the Logger instance explicitly to
every class, we will end up with references to it in various parts of the program, impacting
code maintainability.
The solution is to utilise the Singleton pattern to provide access to a single global
instance from the SimpleLogger class itself. In Java, a Singleton class can be defined
using a static variable which is accessible globally, as follows:
}
return uniqueInstance; // return the single instance
}
// other public methods here. Singleton is a normal class; it may have other use
ful instance variables and methods
}
The Logger can be accessed from any part of the code using:
SingletonLogger.getInstance();
Notice the different aspects at play here. First of all, direct instantiation of objects (new
instances of this class) is prohibited by making the constructor private. Second, the single
instance is accessed calling the public static getInstance() method. Third, the singleton
class can now be constructed whenever needed, but will throw an error if you try to
construct it more than once.
The Factory pattern, more specifically the Simple Factory pattern, provides a way to
decouple the clients from a concrete class through abstraction.
The class diagram above of this pattern shows the interface or abstract class that allows
instantiation of concrete classes by clients. This is explained further in the following:
Audiotype audio;
if ("MP3")) {
audio = new MP3Player();
} else if ("WAV")) {
audio = new WavPlayer ();
} else if ("AIFF")) {
audio = new AiffPlayer ();
}
Here we have several concrete audio classes, and the decision of the specific one to
instantiate is made at runtime depending on some conditions. Code that makes use of
several concrete classes is error-prone and difficult to maintain and update when it needs
to be changed to add new concrete classes.
This issue can be addressed by utilising the Factory pattern, which helps in defining an
abstract class or interface that handles the details of object creation (for all audio types)
through encapsulation. This assists in keeping the code flexible for modification, while
allowing creation of new instance(s) of a concrete class.
The following shows how the Factory pattern enables encapsulating the parts of code
that change when a new audio type is added from the rest of the application which
remains unchanged. The first step is to separate the object creation code into a new
class (PlayerFactory) that encapsulates object creation for all audios for its clients. Any
other object that needs a new audio to be created, has to come to this object.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 9 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
return audio;
}
}
1. new class, the PlayerFactory, which has the task of creating audio types for its clients
2. First we define a createAudio() method in the factory (which all clients will use to
instantiate new objects) and pass the type of audio to it
3. Based on the type of audio, the correct concrete class is instantiated and assigned to
the audio instance variable. Notice that each audio here has to implement the
Audiotype interface.
Once we have created the interface or Factory (in the form of the createAudio method),
we can create a method (orderAudio) that becomes a client of the Factory and relies on it
for the creation of new audio objects.
Audiotype audio;
3. the orderAudio() method uses the factory to create its audios by simply passing on
the type of the order. Notice that the new operator has been replaced with a create
method (createAudio()) on the factory object to prevent concrete instantiations
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 10 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
4. this code does not change, but just operates on the type of audio
Now, the orderAudio method does not need to know about the various audio types (MP3,
WAV, etc). It can simply get an audio that implements the Audiotype interface, so that it
can call play() or any other relevant method. This prevents concrete instantiations from
the client code.
Notice that although we have seen only one here, the PlayerFactory class can have
many clients. By encapsulating the audio type creation in one class, we can ensure that
modification in code is made in only one place when the implementation changes: the
PlayerFactory is the only class responsible for returning the appropriate player class for
each type of audio file.
The Simple Factory pattern has two variations: the Factory Method (a class creational
pattern) and the Abstract Factory (an object creational pattern). All Factory patterns
promote loose coupling by reducing dependencies of applications on concrete classes,
simplifying refactoring of code.
Factory Method
The intent of the Factory Method as defined in GoF Design Patterns is to "define an
interface for creating an object, but let subclasses decide which class to instantiate."
Where it deviates from the Simple Factory is that, instead of handling object creation in a
separate class (as is the case in Simple Factory), the Factory Method encapsulates it in a
subclass; decoupling the client code in the superclass from the object creation code in
the subclass.
1. Composite
2. Decorator
The primary difference between these two patterns is that Composite composes multiple
components, while a Decorator decorates a single component.
The class hierarchies consist of primitive objects and composite objects. Primitive
objects, which might themselves be composed of objects (a composite), can be
composed into more complex objects, and so on recursively. Forcing relationships into a
part-whole hierarchy in this way minimises the types of objects that a system needs to
manage. Examples of the Composite class can be found in a graphical user interface, in
which a window can contain other widgets. For example, a window can contain a list box
which contains a button.
The Composite pattern makes it easy to model a "has a" relationship, which is particularly
helpful for modelling a tree structure in which every concept/element has its own class.
The solution is to use polymorphism to support tree traversal, without requiring any
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 12 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
In this tree structure, elements with a child/children are called nodes. An element without
a child is called a leaf. In the example of folders/files, the Leaf class would be a File, and
the Composite class the Folder.
Notice the different aspects at play here. First of all, the Client uses the Component
interface to access and manipulate the objects (Leaf and Composite) in the composition.
Second, the Component defines an interface for all objects in the composition; both the
composite and the leaf nodes. Third, the Component may implement a default behaviour
and operations for add() and remove(). Fourth, the Composite’s role is to define
behaviour of the components having children. The Composite also implements Leaf-
related operations.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 14 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
The above code illustrates use of the Composite design pattern. Notice how the show
method is implemented differently in the File (Leaf) class and in the Folder (Composite)
class. In the latter, the show method is called on each of the components of the folder.
The example main code demonstrates how easy it is to set up and show information
about individual files or nested hierarchies of folders.
This design pattern demonstrations good cohesion. Each class performs just one task.
The leaf class, File, is responsible for showing itself. The composite class, Folder, passes
off responsibility for showing its contents to those contents themselves. There is no place
in the code which explicitly works through the entire hierarchy - all is managed implicitly
using polymorphism and recursion. This design is robust, you can see there are no
limitations (beyond those of memory in the Java runtime), and clear. It is also easy to
extend without affecting any of the existing classes: think about adding a symbolic link,
which is a reference to another file - is it clear this would be simply another kind of leaf
object?
The only disadvantage to this pattern is a certain degree of opaqueness - is it clear that
the call to d1.show() is going to show the entire contents of the hierarchy? You do need to
understand the pattern in detail and the individual classes to appreciate exactly how
things are happening. Hence, if you are going to use this, or any other design pattern, in
your own code, it is important to document your intent and use clearly named methods.
We will meet further examples of the Composite class later in this module, most notably
when looking at the Swing API. In a graphical user interface, a window can contain other
widgets recursively, for example, a window can contain a list box which contains a button.
There, the Component class will represent the Leaf class, and the Container class the
Composite.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 15 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
This pattern is commonly used in GUI programming, so we will include an example from
this context. Sometimes we want to add responsibilities to individual objects, as opposed
to an entire class. For example, a graphical user interface toolkit should let you add
behaviours like scrolling and drawing borders to any user interface component.
One way to add responsibilities is with inheritance. Inheriting a border from another class
puts a border around every subclass instance. This leads to inflexibility as the choice of
border is made statically, and a client cannot control how and when to decorate the
component with a border.
A more flexible approach is to enclose the component in another object that adds the
border. The enclosing object is called a decorator. The decorator conforms to the
interface of the component it decorates so that its presence is transparent to the
component’s clients. Transparency permits decorators to be nested recursively, thereby
allowing an unlimited number of added responsibilities.
For example, suppose we have a TextView object that displays text in a window.
TextView has no scroll bars by default, because we might not always need them. When
we do, we can use a ScrollDecorator class to add it. Suppose we also want to add a thick
black border around the TextView. We can use a BorderDecorator class to add this as
well. We simply compose the decorators with the TextView to produce the desired result.
The following class diagram shows how to compose a TextView object with
BorderDecorator and ScrollDecorator objects to produce a bordered, scrollable text view:
VisualComponent is the abstract class (interface) for visual objects. It defines their
drawing and event handling interface. The ScrollDecorator and BorderDecorator classes
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 16 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
are subclasses of the Decorator, an abstract class for visual components that decorate
other visual components. Notice how the Decorator class simply forwards draw requests
to its components, and how the subclasses extend this operation. The Decorator class
maintains a reference to the VisualComponent object and defines an interface that
conforms to the component’s interface. In other words, it has a component object to be
decorated.
Decorator subclasses are free to add operations for specific functionalities. For example,
ScrollDecorator’s scrollTo operation lets other objects add a scrolling functionality to the
interface.
The following class is a concrete implementation of this interface. This is the base class
(without any scroll bars or border) on which the decorators will be added.
The abstract Decorator class, the core of the decorator design pattern which wraps
behaviours of subclasses, is then implemented. Notice that this class implements the
VisualComponent class and contains an instance of a visualcomponent object (that is
assigned dynamically at creation using its constructor), as well as methods that the
visualcomponent interface defines. Once assigned, the instance methods can be invoked
(this is called delegation).
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 17 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
super(interfaceReference);
}
Notice the use of the keyword 'super' above. This is used to access superclass members.
As the draw() method in this subclass overrides the superclasses’s method, you can
invoke the overridden method through the use of this keyword.
// draw border
}
Finally, we create the text view decorated with scroll bar and border:
// instantiating
TextView textView = new TextView();
This creates a text view decorated with scroll bar and border. Notice how the scrolling
and border functionalities have been added dynamically at runtime. This makes it easy to
include decorations as needed.
1. Iterator
2. Observer
3. Template
4. Strategy
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 19 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
4. Strategy
The intent of the Iterator pattern as defined in Design Patterns is to, "Provide a way to
access the elements of an aggregate object sequentially without exposing its underlying
representation."
Notice the Iterator object extracted from the list. The Iterator pattern relies on an
interface. The hasNext() method tells us if there are more elements in the aggregate to
iterate through. The next() method returns the next object in the aggregate. Once we
have this interface, we can implement Iterators of various kinds of collections of objects
including arrays, lists, hashmaps etc. All aggregate objects which implement the Iterator
interface provide the same methods, and there is a consistent way to access the
elements within the aggregate.
We shall discuss this pattern further later in the module, when looking at the collections
classes in more detail.
Imagine an application storing data from a scientific experiment. There are numbers
about timings and weights and measurements of various kinds. As the experiment runs,
these numbers are constantly being updated. The scientist watching the experiment may
have a graph open showing the different weights against time. They may also have a
table showing the average weight over the last 10 measurements. Other graphs and
charts may present other aspects of the same data. How do we ensure all these graphs
and charts (the views) get updated every time a new measurement comes in?
The solution is the Observer design pattern, which is a way to register certain observing
classes with an observable class: in our example, the stored data from the
measurements would be held in an observable class, and the different graphs and charts
would be different observing classes. The idea is quite simple: as the observed class
changes, it tells all its observers to update themselves.
1. As part of the initialisation, Views (Observer) register with the Model (Subject)
4. Apart from this, and the fact that each View implements the Observer interface, the
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 21 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
4. Apart from this, and the fact that each View implements the Observer interface, the
Model knows nothing about the details of the Views.
The following is a general class diagram for the Observer pattern. Subjects (observables)
update Observers using a common interface. They define a one-to-many relationship:
1. When the Model is updated by its Controller class, the Model broadcasts a notification
that it has changed to each registered View, by calling their update method, through
notifyObservers.
2. update in each View calls back to retrieve the Model’s state ("pull" implementation)
The Observer pattern can be implemented in two ways, depending on how we wish to
deal with a change in the model: we can either send ("push") data out to the views and let
them process the data, or we can tell the views that we have changed, and lets them
interrogate the appropriate methods of the model ("pull").
The latter technique means that the model can be developed independently of the view.
The view is then developed based around the methods that the model exposes. The
Observer pattern ensures loose coupling by providing an object design in which the
objects can interact but have very little knowledge of each other.
package observerexample;
import java.util.List;
import java.util.ArrayList;
public Model () {
values = new ArrayList<String> ();
}
// call the following method first to indicate the state has changed
setChanged ();
// before calling notifyObservers()
notifyObservers (); // model has changed, so let observers know. (1)
}
setChanged ();
notifyObservers (); // model has changed, so let observers know
}
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 23 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
}
}
1. Notice that in this case, the Observer has to "pull" the data it needs from the
Observable object. If you want to "push" data to the observers, you can pass the data
as argument to this method.
The following code creates an Observer object. To be an observer, the object must
implement the update method. This gets called when the model calls notifyObservers. To
implement the "pull" technique, the view is created with a reference to the observed
Model. This enables the view to update its display or print out information by interrogating
the object directly.
package observerexample;
this.model = model;
this.name = name;
}
Finally, the following Main class shows how a model can be created and observers added
and removed at will. Notice that addObserver and deleteObserver are implemented by
the Observable superclass.
package observerexample;
import java.util.*;
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 24 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
}
}
Make sure you run the code above and understand the different stages in the
addition/deletion of observers.
As you have seen above, using Java’s built-in Observer pattern (the Observer interface
and the Observable class in the java.util package), you can extend the Observable class
to tell it when to notify the Observers. The API handles the rest.
interface (it 'extends' the Observer interface). For an alternative, and to see how this
issue can be addressed, refer to pgs. 57-60 of Head First Design Patterns.
The next two patterns, Template Method and Strategy, are similar in that they allow
different implementations for a fixed set of behaviours. However, while the focus of
Template is to enforce consistency, the focus of Strategy is to allow variety.
The problem that this pattern addresses is when mostly the same sequence of steps is
performed but some parts need specialising. As an example, consider outputting the text
for a report. This may sometimes need to be outputted as plain text, sometimes in HTML,
sometimes in PDF, etc. However, in all cases, the same header or a particular section of
the body will be output.
// abstract class
public abstract class ReportWriter {
private String title; // (1)
private String[] text; // (2)
// concrete subclass
public void outputBody () { // (5)
for (String line : text) {
outputLine (line);
}
}
public abstract void outputStart ();
public abstract void outputHead ();
public abstract void outputBodyStart ();
public abstract void outputBodyEnd ();
public abstract void outputEnd ();
public abstract void outputLine ();
}
4. Each step of the algorithm is implemented (in the subclass) as a separate method.
Besides these, any method(s) specific to a subclass are declared abstract.
}
public void outputEnd () {
System.out.println ("</html>");
}
}
Notice how the concrete class simply implements each of the hook methods in turn. The
concrete class has no knowledge of the underlying algorithm or order in which these
methods will be called. This enables creating new implementations for a general
algorithm (this is placed in the base class).
The Template Method pattern is sometimes used to implement hooks in a system, such
as an application framework (discussed in the next session).
The AbstractClass (as seen in class diagram above) contains the template method. The
PrimitiveOperations in this class are abstract versions of the operations that are
decoupled form the actual implementation (concrete operations). There may be several
ConcreteClasses that implement the abstract operations, which are called when the
TemplateMethod() needs them.
The AbstractClass contains abstract methods for the primitive operations, which act as
hooks for the concrete classes to fill out.
This pattern gives us an important technique for code reuse. You can see many
examples of its use in real-world code.
While this pattern is easy to understand, it is easy to overlook in practice. The same
applies for the Strategy pattern, which we will explore next. Also, the Template Method
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 28 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
and the Strategy patterns both encapsulate algorithms; the first one by inheritance and
the second one by composition. The Factory Method (which is discussed briefly in
session 2) is a specialisation of the Template Method.
The intent of the Strategy pattern as defined in Design Patterns is to, "Define a family of
algorithms, encapsulate each one, and make them interchangeable." It allows the
algorithm to vary independently, as the clients request.
An example might be a program for playing music: the music may be in different formats,
MP3, WAV, Midi files, etc. The music program needs to operate in the same way, no
matter which algorithm it is using to interpret the music format.
The solution is to encapsulate the algorithm in an object. Different classes provide the
different implementations. In Java, we make each class implement the same interface.
client code is then written in terms of the interface, rather than a concrete class
implementation
client is decoupled from the class that provides it with the service
service provider can be replaced by a different one without any effect on the client
code.
This pattern has become a pervasive style of doing object-oriented development: often
known by the phrase "Program to an interface, not an implementation", that we have
discussed in the previous unit.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 29 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
The figure above illustrates the design behind the Strategy pattern. The code below
shows a sketch of the code for the music example. Notice how the different classes
implementing the AudioPlayer interface have no other connection as classes. However,
by implementing the same interface, they can all be plugged into the MusicPlayer:
This concludes the tour of the Creational, Structural, and Behavioural design patterns.
The patterns discussed here ultimately deal with abstracting concepts and algorithms into
classes and objects. While patterns provide an elegant way of designing applications, be
cautious of their overuse.
4.5. Frameworks
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 30 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
Having explored concept reuse using design patterns in the previous sessions, this
session looks at design reuse using frameworks, which are generic structures that can be
extended to create a more specific sub-system or application. Frameworks enable object
reuse in an object-oriented development process through larger-grained abstractions.
information exchange. Examples include Microsoft’s .NET and Enterprise Java Beans
(EJB).
The most widely-used application frameworks are Web Application Frameworks (WAFs)
that facilitate the construction of dynamic website by providing components and classes
that support dynamic web pages, database integration, user interaction, session
management, etc. The architecture of a WAF is normally based on the Model View
Controller (MVC) Compound pattern (a pattern of patterns), which was originally
proposed as an approach to GUI design. In essence, MVC separates the state from its
presentation. This description might help you to relate it to the Observer pattern
discussed in session 4. An example is Swing, which, like many GUI frameworks, makes
use of the Observer pattern.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 32 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
The fundamental problem with frameworks is their inherent complexity and steep learning
curve. Besides, although they are an effective approach to reuse, they result in "inversion
of control" between the application and the framework on which it is based. A framework
restricts operation names and calls, necessitating their conformance to the specified
conventions. This can impose a constraint on design decisions.
4.6. Exercises
Exercise 1
Identify the Design Patterns from the following descriptions:
Exercise 2
Using the Singleton pattern, design an incremental counter with two methods: one
method that increments the count, and the other that displays the latest count (up to 10).
Exercise 3
Session 2 of this unit discusses the Factory pattern, including the Factory Method. Your
task is to explore the other variation, Abstract Factory, and share a brief review on its
Intent and the feature that distinguishes it from the Factory Method. Share your review on
the discussion forum in StudyNet.
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 33 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
Exercise 4
(QUESTION DELETED)
Exercise 5
Model View Controller (MVC), mentioned in session 5, is considered as a set of patterns
working together in the same design. Which 3 patterns discussed here are used in the
MVC framework? What are their roles in the framework?
Exercise 6
It is often observed that overuse or unnecessary use of design patterns can be counter-
productive. What are the downsides of using Design Patterns? Think for yourself about
some of the potential problems, try some searching for similar or opposing views in
published books/papers, and try to come to a conclusion. Share your ideas on the
StudyNet discussion forum.
Exercise 7
Imagine writing a program to model someone cooking a recipe. There are basic tasks,
such as beating an egg, taking a quantity of flour. Then more complex tasks, such as
making batter, rely on the more basic tasks. Making a cake might rely on making a batter,
preparing a cake tin, etc. Which design pattern or patterns would help organise this
program? Sketch out some sample classes in code or UML to capture the design.
Exercise 8
The following diagram illustrates the layout of the InputStream libraries within the Java
API. Explain how these implement the Decorator design pattern, and provide some
example code illustrating the wrapping process. How is the Template pattern used?
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 34 of 35
Design Patterns and Frameworks: 6WCM0027-0105-2021 - Programming & Software Engineering Practice (COM) 25/04/2022, 4:03 PM
https://herts.instructure.com/courses/92276/pages/design-patterns-and-frameworks?module_item_id=1778082 Page 35 of 35