Software design patterns

Background:

Save Time On Research and Writing
Hire a Pro to Write You a 100% Plagiarism-Free Paper.
Get My Paper

ShoppersLand Inc. is the leading retail chain in Canada. We offer a large range of products including food, clothing, electronics, and pharmaceutical drugs. As a company we strive to provide the best shopping experience for our customers. We are continually trying to find innovative ways to help shoppers have a better experience in our stores. 

We would like to develop an online system, i.e., SmartShoppers, to allow customers to find products in our stores with greater precision than the current system. When open the system, the user will need to specify their postal code and/or their city and province. They will then be presented with a list of stores within their area to choose from as the location they will be shopping at. There should also be a feature which lets the user save this store as their location for future use. The user should also be able to change the store location any time they wish. The user should then be able to create a shopping list by searching for products and by viewing a list of sale items at the store they specified. An algorithm should then provide the user with the list in the best order in which to find the items, starting at the front of the store. Users should also be able to click on items to see a product description, price and where in the store it can be found. The user should also be able to view a list of suggested items. This list would consist of products that others have searched for when they have also searched for items on the users shopping list. 

Tasks: 

a): please apply at least one design pattern we have introduced, and explain which requirements you think the patterns can help.

Save Time On Research and Writing
Hire a Pro to Write You a 100% Plagiarism-Free Paper.
Get My Paper

b): design a system that can meet the requirements described above via class diagrams, and describe how you design can meet the requirements. Please show the details of classes (including attributes, methods, and relations among classes) in your class diagrams. YOU MUST USE 

https://app.diagrams.net/

 to draw your diagram and submit the ” ” of your class diagram, penalty will be imposed for violation.

Design Patterns
EECS 3311

Song Wang
wangsong@eecs.yorku.ca

eecs.yorku.ca/~wangsong/

Overview of Last Lectures

▪ Introduction to Design Patterns
▪ Pattern’s Elements

▪ Types of Design Patterns

▪ Java Design Patterns
▪ The Singleton Pattern

▪ The Factory Pattern

▪ The Builder Pattern

▪ The Prototype Pattern

• Only your first Attempt counts

Average

of Quiz 4 is 76.9%

Quiz 4

70

72

74

76

78

80

82

84

86

88

Quiz 1 Quiz 2 Quiz 3 Quiz 4

Average

Average

Acknowledge

• Some of the covered materials are based on SOEN
344 at Concordia, SE463 at UW, SENG321 at UVic,
CSE331 at University of Washington and previous
EECS3311 offerings:

• Nikolaos Tsantalis, Jo Atlee, Marty Stepp, Mike
Godfrey, Jonathan S. Ostroff, M. Ernst, S. Reges, D. Notkin,
R. Mercer, Davor Svetinovic, Jack Jiang, Jackie Wang

Outlines

▪ Java Design Patterns
▪ The Adapter Pattern

▪ The Bridge Pattern

▪ The Composite Pattern

Visitor Design Pattern

▪ Iterator Pattern

▪ State Design Pattern

▪ Event-driven pattern

▪ Observer design patterns

Pattern: Adapter

▪ Structural patterns describe how classes and objects can be combined to

form larger structures.

▪ The difference between class patterns and object patterns is that class patterns

describe how inheritance can be used to provide more useful program

interfaces.

▪ Object patterns, on the other hand, describe how objects can be composed into

larger structures using object composition, or the inclusion of objects within

other objects.

▪ The Structural patterns are:

▪ Adapter

▪ Bridge

▪ Composite

▪ Proxy

▪ Flyweight

▪ Facade

▪ Decorator

Structural Patterns

▪ The Adapter pattern can be used to make one class interface

match another to make programming easier.

▪ The Bridge pattern separates an object’s interface from its

implementation, so you can vary them separately.

▪ The Composite pattern is a composition of objects, each of which

may be either simple or itself a composite object.

▪ The Proxy pattern is frequently a simple object that takes the

place of a more complex object that may be invoked later, for

example when the program runs in a network environment.

Structural Patterns (cont.)

▪ The Flyweight pattern is a pattern for sharing objects, where each

instance does not contain its own state, but stores it externally.

This allows efficient sharing of objects to save space, when there

are many instances, but only a few different types.

▪ The Facade pattern is used to make a single class represent an

entire subsystem.

▪ The Decorator pattern, which can be used to add responsibilities

to objects dynamically.

Structural Patterns (cont.)

▪ Adapters are used to enable objects with different interfaces to

communicate with each other.

▪ The Adapter pattern is used to convert the programming interface

of one class into that of another. We use adapters whenever we

want unrelated classes to work together in a single program.

▪ Adapters come in two flavors, object adapters and class

adapters.

▪ The concept of an adapter is: we write a class that has the desired

interface and then make it communicate with the class that has a

different interface.

▪ Adapters in Java can be implemented in two ways: by

inheritance, and by object composition.

Adapter Pattern:
Definition & Applicability

▪ Object adapters use a compositional technique to adapt one interface to

another.

▪ The adapter inherits the target interface that the client expects to see, while it

holds an instance of the adaptee.

▪ When the client calls the request() method on its target object (the adapter), the

request is translated into the corresponding specific request on the adaptee.

▪ Object adapters enable the client and the adaptee to be completely decoupled

from each other. Only the adapter knows about both of them.

Adapter Pattern: Object Adapters

/**

* The SquarePeg class.

* This is the Target class.

*/

public class SquarePeg

{

public void insert(String str) {

System.out.println(“SquarePeg insert():

” + str);

}

}
/**

* The RoundPeg class.

* This is the Adaptee class.

*/

public class RoundPeg {

public void insertIntoHole(String msg) {

System.out.println(“RoundPeg insertIntoHole(): ” + msg);}

}

If a client only understands the SquarePeg interface for inserting pegs
using the insert() method, how can it insert round pegs, which are pegs, but
that are inserted differently, using the insertIntoHole() method?

Adapter Pattern:
Example

Solution:

Design a RoundToSquarePeg adapter that enables to insertIntoHole() a
RoundPeg object connected to the adapter to be inserted as a SquarePeg,
using insert().

/**
* The RoundToSquarePegAdapter class.
* This is the Adapter class.
* It adapts a RoundPeg to a SquarePeg.
* Its interface is that of a SquarePeg.
*/
public class RoundToSquarePegAdapter extends SquarePeg {

private RoundPeg roundPeg;
public RoundToSquarePegAdapter(RoundPeg peg) {
//the roundPeg is plugged into the adapter

this.roundPeg = peg;}

public void insert(String str) {
//the roundPeg can now be inserted in the same manner as a squarePeg!

roundPeg.insertIntoHole(str);}

}
Adapter Pattern:
Example

Example:
// Test program for Pegs.

public class TestPegs {

public static void main(String args[]) {

// Create some pegs.

RoundPeg roundPeg = new RoundPeg();

SquarePeg squarePeg = new SquarePeg();

// Do an insert using the square peg.

squarePeg.insert(“Inserting square peg…”);

// Now we’d like to do an insert using the round peg.

// But this client only understands the insert()

// method of pegs, not a insertIntoHole() method.

// The solution: create an adapter that adapts

// a square peg to a round peg!

RoundToSquarePegAdapter adapter = new RoundToSquarePegAdapter(roundPeg);

adapter.insert(“Inserting round peg…”);}

}

Execution trace:

SquarePeg insert(): Inserting square peg…

RoundPeg insertIntoHole(): Inserting round peg…

Adapter Pattern:
Example

▪ Class adapters use multiple inheritance to achieve their goals.

▪ As in the object adapter, the class adapter inherits the interface of the client’s

target. However, it also inherits the interface of the adaptee as well.

▪ Since Java does not support true multiple inheritance, this means that one of

the interfaces must be inherited from a Java Interface type.

▪ Both of the target or adaptee interfaces could be Java Interfaces.

▪ The request to the target is simply rerouted to the specific request that was

inherited from the adaptee interface.

Adapter Pattern: Class Adapters

Here are the interfaces for round and square pegs:

/**

*The IRoundPeg interface.

*/

public interface IRoundPeg {

public void insertIntoHole(String msg);

}
/**

*The ISquarePeg interface.

*/

public interface ISquarePeg {

public void insert(String str);

}
Adapter Pattern:
Example

Here are the new RoundPeg and SquarePeg classes. These are essentially the
same as before except they now implement the
appropriate interface.

// The RoundPeg class.

public class RoundPeg implements IRoundPeg {

public void insertIntoHole(String msg) {
System.out.println(“RoundPeg insertIntoHole(): ” + msg);}
}

// The SquarePeg class.

public class SquarePeg implements ISquarePeg {

public void insert(String str) {

System.out.println(“SquarePeg insert(): ” + str);}

}
Adapter Pattern:
Example

And here is the new PegAdapter class:

/**

* The PegAdapter class.

* This is the two-way adapter class.

*/

public class PegAdapter implements ISquarePeg, IRoundPeg {

private RoundPeg roundPeg;

private SquarePeg squarePeg;

public PegAdapter(RoundPeg peg) {

this.roundPeg = peg;}

public PegAdapter(SquarePeg peg) {

this.squarePeg = peg;}

public void insert(String str) {
roundPeg.insertIntoHole(str);}

public void insertIntoHole(String msg){

squarePeg.insert(msg);}

}
Adapter Pattern:
Example

A client that uses the two-way adapter:
// Test program for Pegs.

public class TestPegs {
public static void main(String args[]) {
// Create some pegs.
RoundPeg roundPeg = new RoundPeg();
SquarePeg squarePeg = new SquarePeg();
// Do an insert using the square peg.
squarePeg.insert(“Inserting square peg…”);

// Create a two-way adapter and do an insert with it.

ISquarePeg roundToSquare = new PegAdapter(roundPeg);

roundToSquare.insert(“Inserting round peg…”);

// Do an insert using the round peg.

roundPeg.insertIntoHole(“Inserting round peg…”);

// Create a two-way adapter and do an insert with it.

IRoundPeg squareToRound = new PegAdapter(squarePeg);

squareToRound.insertIntoHole(“Inserting square peg…”);}

}
Adapter Pattern:
Example

Client program output:

SquarePeg insert(): Inserting square peg…
RoundPeg insertIntoHole(): Inserting round peg…
RoundPeg insertIntoHole(): Inserting round peg…
SquarePeg insert(): Inserting square peg…
Adapter Pattern:
Example

Class and object adapters have different trade-offs.

A class adapter:

▪ adapts Adaptee to Target by committing to a concrete Adapter class;

▪ lets Adapter override some of Adaptee’s behavior, since Adapter is a

subclass of Adaptee;

▪ introduces only one object, and no additional indirection is needed to get

to the adaptee.

An object adapter

▪ lets a single Adapter work with many Adaptees – that is, the Adaptee itself

and all of its subclasses (if any). The Adapter can also add functionality to all

Adaptees at once.

▪ makes it harder to override Adaptee behavior. It will require subclassing

Adaptee and making Adapter refer to the subclass rather than the Adaptee

itself.

Adapter Pattern:
Consequences of the Adapter Pattern

Pattern: Bridge

The Bridge pattern is used to separate the interface of class from its
implementation, so that either can be varied separately.

▪ At first sight, the bridge pattern looks much like the Adapter pattern, in
that a class is used to convert one kind of interface to another. However,
the intent of the Adapter pattern is to make one or more classes’
interfaces look the same as that of a particular class.

▪ The Bridge pattern is designed to separate a class’ interface from its
implementation, so that you can vary or replace the implementation
without changing the client code.

Example:

Suppose that we have a program that displays a list of products in a window.
The simplest interface for that display is a simple JList box. But, once a
significant number of products have been sold, we may want to display the
products in a table along with their sales figures.

The Bridge Pattern
Definition & Applicability

Following the example from the previous slide, suppose that we need to make

some changes in the way these lists display data. So, rather than deriving new

classes whenever we need to change these displays further, let’s build a single

bridge that does this work for us.

Building the Bridge Pattern

We want the bridge class to return an appropriate visual component, so we will

extend the Java JSrollPane class:

public class ListBridge extends JScrollPane

{…}

When we design a bridge class, we have to decide how the bridge will determine

which of the several classes it will instantiate. This could be decided based on the

values or quantity of data to be displayed, or based on some simple constants.

Here we define the two constants inside the ListBridge class:

static public final int TABLE = 1, LIST = 2;

Building the Bridge Pattern

The constructor of the ListBridge class:

public ListBridge(Vector v, int table_type)

{

Vector sort = sortVector(v); //sort the vector

if (table_type == LIST)

getViewport().add(makeList(sort)); //make

table

if (table_type == TABLE)

getViewport().add(makeTable(sort)); //make

list

}
Building the Bridge Pattern

We can use the JTable and JList classes directly without modification and thus

can put any adapting interface computations in the data models that construct the

data for the list and table.

private JList makeList(Vector v) {

return new JList(new ListModel(v));

}

//———————————

private JTable makeTable(Vector v) {

return new JTable(new TableModel(v));

}

Where ListModel and TableModel are Java API classes.

Building the Bridge Pattern

public class ListBridge extends JScrollPane{

static public final int TABLE = 1, LIST = 2;
private JList makeList(Vector v) {
return new JList(new ListModel(v));
}
private JTable makeTable(Vector v) {
return new JTable(new TableModel(v));
}

public ListBridge(Vector v, int table_type) { //constructor

Vector sort = sortVector(v); //sort the vector
if (table_type == LIST)

getViewport().add(makeList(sort)); //make

table
if (table_type == TABLE)

getViewport().add(makeTable(sort)); //make

list
}
}

The Bridge Pattern Class

▪ The Bridge pattern is intended to keep the interface to your client

program constant while allowing you to change the actual kind of

class you display or use.

▪ This can prevent you from recompiling a complicated set of user

interface modules, and only require that you recompile the bridge

itself and the actual end display class.

▪ You can extend the implementation class and the bridge class

separately, and usually without much interaction with each other.

Consequences of the Bridge Pattern

Pattern: Composite

The Composite Design pattern allows a client object to treat both

single components and collections of components identically.

Composite patterns are often used to represent recursive data

structures. The recursive nature of the Composite structure naturally

gives way to recursive code to process that structure.

Use the Composite pattern when:

▪ You want to represent part-whole hierarchies of objects.

▪ You want clients to be able to ignore the difference between

compositions of objects and individual objects. Clients will

treat all objects in the composite structure uniformly.

The Composite Pattern
Definition & Applicability

In the UML class diagram below:

▪ The Client uses an abstract component, AComponent, for some abstract task,

operation().

▪ At run-time, the Client holds a reference to a concrete component such as

Leaf1 or Leaf2.

▪ When the operation task is requested by the Client, the specific concrete

behavior with the particular concrete component will be performed.

The Composite Pattern Example

▪ The Composite pattern allows you to define a class hierarchy of

simple objects and more complex composite objects so that they

appear to be the same to the client program.

▪ Because of this simplicity, the client can be that much simpler,

since nodes and leaves are handled in the same way.

▪ The Composite pattern also makes it easy for you to add new

kinds of components to your collection, as long as they support a

similar programming interface.

▪ The composite is essentially a singly-linked tree, in which any of

the objects may themselves be additional composites.

Consequences of the Composite Pattern

Design Patterns
EECS 3311

Song Wang
wangsong@eecs.yorku.ca

eecs.yorku.ca/~wangsong/

Overview of Last Lectures
• Control Flow Graphs

• If Statements
• Loop Statements

• Code Coverage
• JaCoCo

• UML
• Use Case Diagram
• Activity Diagram
• Sequence Diagram
• Class Diagram

• different relations

• Only your first Attempt counts

Average

of Quiz 3 is 85.8%

Quiz 3

84.4

84.6

84.8

85

85.2

85.4

85.6

85.8

86

86.2

Quiz 1 Quiz 2 Quiz 3

Average

Average

Acknowledge

• Some of the covered materials are based on SE463
at UW, SENG321 at UVic, CSE331 at University of
Washington and previous EECS3311 offerings:
• Jo Atlee, Dan Berry, Daniela Damian, Marty Stepp, Mike

Godfrey, Jonathan S. Ostroff, M. Ernst, S. Reges, D. Notkin,
R. Mercer, Davor Svetinovic, Jack Jiang, Jackie Wang

Outlines

▪ Introduction to Design Patterns

Pattern’s Elements

▪ Types of Design Patterns

▪ Java Design Patterns
▪ The Singleton Pattern
▪ The Factory Pattern
▪ The Builder Pattern
▪ The Prototype Pattern
▪ The Adapter Pattern
▪ The Bridge Pattern
▪ The Composite Pattern
▪ Visitor Design Pattern
▪ Iterator Pattern
▪ State Design Pattern
▪ Event-driven pattern
▪ Observer design patterns

Design patterns
• Design pattern: A standard solution to a common

software problem in a context.

• describes a recurring software structure or idiom
• is abstract from any particular programming language
• identifies classes and their roles in the solution to a

problem

• In 1990 a group called the Gang of Four or “GoF”
(Gamma, Helm, Johnson, Vlissides) compile a
catalog of design patterns
• 1995 book Design Patterns:

Elements of Reusable Object-Oriented
Software is a classic of the field

In general, a pattern has four essential elements.

▪ The pattern name

▪ The problem

▪ The solution

▪ The consequences

Pattern’s Elements

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.

Pattern’s Elements – The Pattern Name

The problem describes when to apply the

pattern.

▪ 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.

Pattern’s Elements – The Problem

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.

Pattern’s Elements – The Solution

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 and

evaluate them.

Pattern’s Elements – The Consequences

Benefits of using patterns

• Patterns give a design common vocabulary for software
design:
• Allows engineers to abstract a problem and talk about that

abstraction in isolation from its implementation.

• A culture; domain-specific patterns increase design speed.

• Capture expertise and allow it to be communicated:
• Promotes design reuse and avoid mistakes.

• Makes it easier for other developers to understand a system.

• Improve documentation (less is needed):
• Improve understandability (patterns are described well, once).

Gang of Four (GoF) patterns
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.

Gang of Four (GoF) patterns (cont.)

• Creational Patterns (abstracting the object-instantiation process)
• Singleton Factory

• Builder Prototype

• Structural Patterns (how objects/classes can be combined)
• Adapter Bridge Composite

• Decorator Facade Flyweight

• Proxy

• Behavioral Patterns (communication between objects)
• Command Interpreter Iterator

• Observer State

• Visitor Even-driven …

Pattern: Singleton
A class that has only a single instance

Singleton pattern

• singleton: An object that is the only object of its type.
(one of the most known / popular design patterns)

• Ensuring that a class has at most one instance.

• Providing a global access point to that instance.
• e.g. Provide an accessor method that allows users to see the instance.

• Benefits:
• Takes responsibility of managing that instance away from the

programmer (illegal to construct more instances).

• Saves memory.

• Avoids bugs arising from multiple instances.

Restricting objects

• One way to avoid creating objects: use static methods
• Examples: Math, System

• Is this a good alternative choice? Why or why not?

• Disadvantage: Lacks flexibility.
• Static methods can’t be passed as an argument, nor

returned.

• Disadvantage: Cannot be extended.
• Static methods can’t be subclassed and overridden like an

object’s methods could be.

• Make constructor(s) private so that they can not be
called from outside by clients.

• Declare a single private static instance of the class.

• Write a public getInstance() or similar method that
allows access to the single instance.

• May need to protect / synchronize this method to ensure
that it will work in a multi-threaded program.

Implementing Singleton

Singleton sequence diagram

• Class RandomGenerator generates random numbers.

public class RandomGenerator

{

private static final RandomGenerator gen =

new RandomGenerator();

public static RandomGenerator getInstance() {

return gen;

}

private RandomGenerator() {}

}

Singleton example

• Can wait until client asks for the instance to create it:

public class RandomGenerator {

private static RandomGenerator gen = null;

public static RandomGenerator getInstance() {

if (gen == null) {

gen = new RandomGenerator();

}
return gen;
}
private RandomGenerator() {}

}

Lazy initialization

Pattern: Factory

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 getClass() 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.

How does it Work?

▪ 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”(a comma in-between).
▪ Let’s make the assumption that we will always be able to decide the name

order by whether there 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 getFirst() {

return first; //return first name

}

public String getLast() {

return last; //return last name

}
}

The Base Class

In the FirstFirst class, we assume that everything before the last

space is part of the first name.

class FirstFirst extends Namer {

public FirstFirst(String s) {

int i = s.lastIndexOf(” “); //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

}
}
}

The First Derived Class

In the LastFirst class, we assume that a comma delimits the last

name.

class LastFirst extends Namer { //split last, first

public LastFirst(String s) {

int i = s.indexOf(“,”); //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

}
}
}

The Second Derived Class

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 NameFactory {

//returns an instance of LastFirst or FirstFirst

//depending on whether a comma is found

public Namer getNamer(String entry) {

int i = entry.indexOf(“,”); //comma determines name order

if (i>0)

return new LastFirst(entry); //return one class

else

return new FirstFirst(entry); //or the other

}
}

Building the Factory

NameFactory nfactory = new NameFactory();

String sFirstName, sLastName;

….

private void computeName() {

//send the text to the factory and get a class back

namer = nfactory.getNamer(entryField.getText());

//compute the first and last names using the returned class

sFirstName = namer.getFirst();

sLastName = namer.getLast();

}

Using the Factory

You should consider using a Factory pattern when:

▪ Create objects dynamically

▪ 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.

When to Use a Factory Pattern

The Abstract Factory pattern is one level of abstraction higher than the factory

pattern. This 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.

The Abstract Factory Pattern
How does it Work?

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 getCenter();

public abstract Plant getBorder();

public abstract Plant getShade();

}

A Garden Maker Factory

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 getName() {

return name;

}
}

The Plant Class

A Garden class simply returns one kind of each plant. So, for example, for the

vegetable garden we simply write:

public class VegieGarden extends Garden {

public Plant getShade() {

return new Plant(“Broccoli”);

}

public Plant getCenter() {

return new Plant(“Corn”);

}

public Plant getBorder() {

return new Plant(“Peas”);

}
}

A Garden Class

We create a series of Garden classes – VegieGarden, PerennialGarden, and

AnnualGarden, 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 GardenMaker {

//Abstract Factory which returns one of three gardens

private Garden gd;

public Garden getGarden(String gtype) {

gd = new VegieGarden(); //default

if(gtype.equals(“Perennial”))

gd = new PerennialGarden();

if(gtype.equals(“Annual”))

gd = new AnnualGarden();

return gd;

}
}

A Garden Maker Class – The 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.

Consequences of Abstract Factory

Pattern: Builder

The Builder Pattern separates the construction of a complex object from its

representation so that the same construction process can create different

representations.

▪ Builder – specifies an interface for creating parts of a Product object.

▪ ConcreteBuilder – constructs and assembles parts of the product by

implementing the Builder interface. Also, it defines and keeps track of the

representation it creates and provides an interface for retrieving the product .

▪ Director – constructs an object using the Builder interface.

▪ Product – represents the complex object under construction.

How does it Work?

▪ The client creates the Director object and configures it with the desired

Builder object.

▪ Director notifies the builder whenever a part of the product should be built.

▪ Builder handles requests from the director and adds parts to the product.

▪ The client retrieves the product from the builder.

The following interaction diagram illustrates how Builder and Director cooperate

with a client.

How does it Work?

Use the Builder pattern when:

▪ The algorithm for creating a complex object should be

independent of the parts that make up the object and how they

are assembled.

▪ The construction process must allow different representations for

the object that is constructed.

Applicability of Builder Pattern

▪ A Builder lets you vary the internal representation of the product it builds. It

also hides the details of how the product is assembled.

▪ Each specific builder is independent of the others and of the rest of the

program. This improves modularity and makes the addition of other builders

relatively simple.

▪ Because each builder constructs the final product step-by-step, depending on

the data, you have more control over each final product that a Builder

constructs.

▪ A Builder pattern is somewhat like an Abstract Factory pattern in that

both return classes made up of a number of methods and objects. The main

difference is that while the Abstract Factory returns a family of related

classes, the Builder constructs a complex object step by step depending on the

data presented to it.

Consequences of Builder Pattern

/** “Product” */

class Pizza {

private String dough = “”; //basic element

private String sauce = “”; //basic element

private String topping = “”; //basic element

public void setDough(String dough) {

this.dough = dough;

}

public void setSauce(String sauce) {

this.sauce = sauce; }

public void setTopping(String topping) {

this.topping = topping; }

}

Pizza Builder

/** “Abstract Builder” */

abstract class PizzaBuilder {

protected Pizza pizza;

public Pizza getPizza() {

return pizza; }

public void createNewPizzaProduct() {

pizza = new Pizza(); }

public abstract void buildDough();

public abstract void buildSauce();

public abstract void buildTopping();

}
Pizza Builder

/** “ConcreteBuilder” */

class HawaiianPizzaBuilder extends PizzaBuilder {

public void buildDough() {

pizza.setDough(“cross”); }

public void buildSauce() {

pizza.setSauce(“mild”); }

public void buildTopping() {

pizza.setTopping(“ham+pineapple”); }

}
/** “ConcreteBuilder” */

class SpicyPizzaBuilder extends PizzaBuilder {

public void buildDough() {

pizza.setDough(“pan baked”); }

public void buildSauce() {

pizza.setSauce(“hot”); }

public void buildTopping() {

pizza.setTopping(“pepperoni+salami”); }

}
Pizza Builder

/** “Director” */

class Waiter {

private PizzaBuilder pizzaBuilder;

public void setPizzaBuilder(PizzaBuilder pb) {

pizzaBuilder = pb; }

public Pizza getPizza() {

return pizzaBuilder.getPizza(); }

public void constructPizza() {

pizzaBuilder.createNewPizzaProduct();

pizzaBuilder.buildDough();

pizzaBuilder.buildSauce();

pizzaBuilder.buildTopping();

}
}
Pizza Builder

/** A customer ordering a pizza. */

class BuilderExample {

public static void main(String[] args) {

Waiter waiter = new Waiter();

PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();

PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

waiter.setPizzaBuilder( hawaiianPizzaBuilder );

waiter.constructPizza();

Pizza pizza = waiter.getPizza();

waiter.setPizzaBuilder(spicyPizzaBuilder);

waiter.constructPizza();

Pizza pizza2 = waiter.getPizza();

}
}
Pizza Builder

Pattern: Prototype

▪ A prototype is a template of any object before the actual object is
constructed.

▪ The Prototype pattern specifies the kinds of objects to create using a
prototypical instance, and create new objects by copying this prototype.

▪ A Protoype pattern is used when creating an instance of a class is very time-
consuming or complex in some way. Then, rather than creating more
instances, you make copies of the original instance and modify them as
appropriate.

Example:

▪ Let’s consider the case of an extensive database where you need to make a
number of queries to construct an answer. Once you have this answer as a
table or ResultSet, you might like to manipulate it to produce other answers
without issuing additional queries.

Definition & Applicability

You can make a copy of any Java object using the clone method.

Jobj j1 = (Jobj)j0.clone();

The clone method always returns an object of type Object. You must

cast it to the actual type of the object you are cloning. There are

three other significant restrictions on the clone method:

▪ It is a protected method and can only be called from within the

same class or the module that contains that class.

▪ You can only clone objects which are declared to implement

the Cloneable interface.

▪ Objects that cannot be cloned throw the CloneNotSupported

Exception.

Cloning in Java – I

This suggests packaging the actual clone method inside the class where it can

access the real clone method:

public class SwimData implements Cloneable {

public Object clone()

{

try{

return super.clone();

}

catch(Exception e) {

System.out.println(e.getMessage());

return null;

}
}
}

Cloning in Java – II

▪This implementation has the advantage of encapsulating the try-catch block

inside the public clone method.

▪Note that if you declare this public method to have the same name “clone,” it

must be of type Object, since the internal protected method has that signature. We

could, however, change the name and do the typecasting within the method

instead of forcing it onto the user:

public SwimData cloneMe() {

try{

return (SwimData)super.clone();

}
catch(Exception e) {
System.out.println(e.getMessage());
return null;
}
}

Cloning in Java – III

Shallow vs. Deep

(Object) Copy in Java

Thanks: https://dzone.com/articles/java-copy-shallow-vs-deep-in-which-you-will-swim

A reference copy, as the name implies, creates a
copy of a reference variable pointing to an object.

An object copy creates a copy of the object itself.

Say we have a Person object. Person object is in fact composed of other objects, as you
can see in Example. Person contains a Name object and an Address object. The Name in
turn, contains a FirstName and a LastName object; the Address object is composed of
a Street object and a City object.

Shallow Copy

Say we have a Person object. Person object is in fact composed of other objects, as you
can see in Example. Person contains a Name object and an Address object. The Name in
turn, contains a FirstName and a LastName object; the Address object is composed of
a Street object and a City object.

Shallow Copy

Shallow Copy

A shallow copy of an object copies the ‘main’ object, but doesn’t
copy the inner objects.

//Overriding clone() method

protected Object clone() throws CloneNotSupportedException

{

Person p1 = (Person) super.clone();

return p1;

}

Deep Copy is a fully independent copy of an object. If we copied
the Person object, we would copy the entire object structure.

Deep Copy in Java


//Overriding clone() method
protected Object clone() throws CloneNotSupportedException
{
Person p1 = (Person) super.clone();

p1.name = (Name) name.clone();

p1.address = (Address) address.clone();

p1.name.firstname = (FirstName) name.firstname.clone();

p1.name.lastname = (LastName) name.lastname.clone();

p1.adress.street = (Street) address.street.clone();

p1.adress.city = (City) address.city.clone();

return p1;
}

Shallow vs. Deep

Let’s write a simple program that reads data from a database and then clones the

resulting object. In our example program, SwimInfo, we just read these data from

a file, but the original data were derived from a large database as we discussed

above.

We create a class called Swimmer that holds one name, club name, sex and time:

class Swimmer {

String name;

int age;

String club;

float time;

boolean female;

public String getName () {return name};

public int getAge () {return age};

public float getTime () {return time};

}

Using the Prototype – I

We create a class called SwimData that maintains a vector of the Swimmers we read in

from the database.

public class SwimData implements Cloneable {

Vector swimmers;

public Swimmer getSwimmer(int i) {

return swimmers.get(i);};

public SwimData(String filename) {

String s = “”;

swimmers = new Vector();

InputFile f = new InputFile(filename); //open file

s= f.readLine(); //read in and parse each line

while(s != null) {

swimmers.addElement(new Swimmer(s));

s= f.readLine();

}

f.close();

}

Using the Prototype – II

We clone this class and sort the data differently in the new class. Again, we clone

the data because creating a new class instance would be much slower, and we

want to keep the data in both forms.

SwimData sdata = new SwimData();

sdata.sortByName(); //sort by name

sxdata = (SwimData)sdata.clone();

sxdata.sortByTime(); //re-sort by time

for(int i=0; i< sxdata.size(); i++)

//display sorted values from clone

{

Swimmer sw = sxdata.getSwimmer(i);

System.out.println(sw.getName()+” “+sw.getTime());

}

In the original class, the records

are sorted by name, while in the

cloned class, they are sorted by

time.

Using the Prototype – III

Using the Prototype pattern:

▪ You can add and remove classes at run time by cloning them as

needed.

▪ You can revise the internal data representation of a class at run

time based on program conditions.

▪ You can also specify new objects at run time without creating a

proliferation of classes and inheritance structures.

Consequences of the Prototype Pattern – I

Difficulties:

▪ One difficulty in implementing the Prototype pattern in Java is

that if the classes already exist, you may not be able to change

them to add the required clone or deep Clone methods. The deep

Clone method can be particularly difficult if all of the class

objects contained in a class cannot be declared to implement the

Serializable interface.

▪ Classes that have circular references to other classes cannot

really be cloned.

▪ The idea of having prototype classes to copy implies that you

have sufficient access to the data or methods in these classes to

change them after cloning. This may require adding data access

methods to these prototype classes so that you can modify the

data once you have cloned the class.

Consequences of the Prototype Pattern – II

Design Patterns
EECS 3311

Song Wang
wangsong@eecs.yorku.ca

eecs.yorku.ca/~wangsong/

Acknowledge

• Some of the covered materials are based on SOEN 344 at
Concordia, SE463 at UW, SENG321 at UVic, CSE331 at
University of Washington and previous EECS3311 offerings:

• Nikolaos Tsantalis, Jo Atlee, Marty Stepp, Mike Godfrey,
Jonathan S. Ostroff, M. Ernst, S. Reges, D. Notkin, R.
Mercer, Davor Svetinovic, Jack Jiang, Jackie Wang

Outlines

▪ Java Design Patterns (Behavioral Patterns)
▪ Visitor Design Pattern

▪ Iterator Pattern

▪ State Design Pattern

▪ Observer design patterns

Pattern: Visitor

What’s It All About?

• Allows for new operations to be defined and used
on elements of an object structure without
changing the contents of those elements.

• The Key is Double Dispatch
• choosing the method to invoke based both on receiver

and argument types

Where Applicable

• Rarely Changing Object Structures

• Using Unrelated Operations

• Many Classes with Differing Interfaces

Visitor design pattern

• Add an accept(Visitor) method to the “element” hierarchy

• Create a “visitor” base class w/ a visit() method for every
“element” type

• Create a “visitor” derived class for each “operation” to do on
“elements”

• Client creates “visitor” objects and passes each
to accept() calls

How it Works

• Concrete Object
Structure

• Assume Rarely
Changing

• Bank Accounts

Add an Inquiry Operation

• Check balances and
display account summary

• Don’t Want to Change
Structure

• Create a Visitor Structure

• Account Visitor

Account Visitor Interface

Inquiry Visitor

Account Structure Change

Account Interface

Checking Account

Savings Account

Main Method

Pattern: Iterator

What’s It All About?

• Provide a way to access the elements of an
aggregate object sequentially without exposing its
underlying representation.

• Separate traversal code from the data collection
itself.

Java Collections

Figure source: https://techvidvan.com/tutorials/wp-content/uploads/sites/2/2020/03/collection-framework-hierarchy-in-java

Basic Structure

• Iterator keeps a Cursor to current location in a collection.

• Most collections store their elements in simple lists. However,
some of them are based on stacks, trees, graphs and other
complex data structures.

• But no matter how a collection is structured, it must provide
some way of accessing its elements so that other code can use
these elements. There should be a way to go through each
element of the collection without accessing the same
elements over and over.

Visualizing iterator pattern at runtime

ArrayList

ArrayList

Person

Iterator

isDonefirst

Iterator for A Binary Tree

Pattern: State Model

Motivating Problem

Consider the reservation panel of an online booking
system:

Motivating Problem

State Transition Diagram

State Pattern

• State Design Pattern allows an object to change
its behavior when the internal state of that object
changes.

• The state design pattern is generally used in
cases where an object depends on its state and
its behavior must be changed during run time
depending on its internal state.

• A typical behavioral design pattern;

• Context: Defines an interface to client to interact. It maintains references
to concrete state object which may be used to define current state of
object.

• State: Defines interface for declaring what each concrete state should do.

• ConcreteState: Provides implementation for methods defined in State.

State Pattern Diagram

A Simple Example

In this example we will model a mobile state scenario.
With respect to alerts, a mobile can be in different
states. For example, vibration and silent. Based on
this alert state, behavior of the mobile changes when
an alert is to be done.

Source: https://www.geeksforgeeks.org/state-design-pattern/

The key classes

• The State Interface

interface MobileAlertState
{

public void alert(AlertStateContext ctx);

}

The key classes

• Context
class AlertStateContext
{

private MobileAlertState currentState;

public AlertStateContext()
{

currentState = new Vibration();

}

public void setState(MobileAlertState state)
{

currentState = state;
}

public void alert()
{

currentState.alert(this);
}

}

The key classes

• States
class Vibration implements MobileAlertState
{

@Override
public void alert(AlertStateContext ctx)
{

System.out.println(“vibration…”);
}

}

class Silent implements MobileAlertState
{

@Override
public void alert(AlertStateContext ctx)
{

System.out.println(“silent…”);
}

}

The key classes

• Demo
class StatePattern
{

public static void main(String[] args)
{

AlertStateContext stateContext = new AlertStateContext();
stateContext.alert();
stateContext.alert();
stateContext.setState(new Silent());
stateContext.alert();
stateContext.alert();
stateContext.alert();

}
}

Output:

vibration…
vibration…
silent…
silent…
silent…

Pattern: Observer

Observer Pattern

• Defines a “one-to-many” dependency between
objects so that when one object changes state,
all its dependents are notified and updated
automatically

• a.k.a Dependence mechanism / publish-
subscribe / broadcast / change-update

Subject

&

Observer

Subject

• the object which will frequently change its state and

upon which other objects depend

• Observer
• the object which depends on a subject and updates

according to its subject’s state.

Observer Pattern – Example

a b c
60

y
x
5030

30
20
10

z 801010 a b c
a

b
c

a = 50%
b = 30%
c = 20%

change notification

requests, modifications

Observers

Subject

Observer Pattern – Working
A number of Observers “register” to receive notifications of changes to the
Subject. Observers are not aware of the presence of each other.

When a certain event or “change” in Subject occurs, all Observers are “notified’.

Observer Pattern – Key Players

• Subject
• has a list of

observers

• Interfaces for attaching/detaching an observer

• Observer
• An updating interface for objects that gets notified of changes in a

subject

ConcreteSubject

• Stores “state of interest” to observers

• Sends notification when state changes

ConcreteObserver

• Implements updating interface

Observer Pattern – UML

Subject

attach (Observer)

detach (Observer)

Notify ()

Observer

Update()

ConcreteObserver
Update()

observerState

ConcreteSubject

SetState()

GetState()

subjectState

observers
subject

For all x in observers{

x.Update();

}

observerState=

subject.getState();

Observer Pattern –
Collaborations

:ConcreteSubject :ConcreteObserver-1 :ConcreteObserver-2

GetState()

Notify()

Update()
SetState()
GetState()
Update()

Observer Pattern – Implementation

interface Observer {

void update (Observable sub, Object arg)

// repaint the pi-chart

}
Java terminology for Subject.

public void addObserver(Observer o) {}

public void deleteObserver (Observer o) {}

public void notifyObservers(Object arg) {}

class Observable {

}

public boolean hasChanged() {}

Observer Pattern – Consequences

• Loosely Coupled
• Reuse subjects without reusing their observers, and vice versa

• Add observers without modifying the subject or other observers

• Abstract coupling between subject and observer
• Concrete class of none of the observers is known

• Support for broadcast communication
• Subject doesn’t need to know its receivers

• Unexpected updates
• Can be blind to changes in the system if the subject is changed (i.e.

doesn’t know “what” has changed in the subject)

Exercise

• Design the system for the flight online booking
system;

• Draw the class diagram of the online booking
system;

Calculate your order
Pages (275 words)
Standard price: $0.00
Client Reviews
4.9
Sitejabber
4.6
Trustpilot
4.8
Our Guarantees
100% Confidentiality
Information about customers is confidential and never disclosed to third parties.
Original Writing
We complete all papers from scratch. You can get a plagiarism report.
Timely Delivery
No missed deadlines – 97% of assignments are completed in time.
Money Back
If you're confident that a writer didn't follow your order details, ask for a refund.

Calculate the price of your order

You will get a personal manager and a discount.
We'll send you the first draft for approval by at
Total price:
$0.00
Power up Your Academic Success with the
Team of Professionals. We’ve Got Your Back.
Power up Your Study Success with Experts We’ve Got Your Back.

Order your essay today and save 30% with the discount code ESSAYHELP