CS 213 SOFTWARE METHODOLOGY
LILY CHANG ASSOCIATE TEACHING PROFESSOR DEPARTMENT OF COMPUTER SCIENCE RUTGERS UNIVERSITY NEW BRUNSWICK FALL 2021
Design Patterns
Copyright By Assignmentchef assignmentchef
What is design pattern?
Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.
What is design pattern?
Designing object-oriented software is hard, and designing reusable object-oriented software is even harder
You must find pertinent objects, factor them into classes at the right granularity, define class interfaces and inheritance hierarchies, and establish key relationships among them
Your design should be specific to the problem at hand but also general enough to address future problems and requirements
Youll find recurring patterns of classes and communicating objects in many object-oriented systems, and these patterns solve specific design problems and make object-oriented designs more flexible, elegant, and ultimately reusable
Gang of Four (GoF)
The book (1994) has been influential to the field of software engineering
The authors are often referred to as the Gang of Four (GoF)
It is considered as an important source for object- oriented design theory and practice (with C++ examples)
Essential components of a pattern
The pattern name
Use to describe a design problem, its solutions, and consequences in a word or two
A vocabulary for communication
The problem
Describes when to apply the pattern
Explains the problem and its context; such as specific design problems, how to represent algorithms as objects, or symptomatic of an inflexible design
The solution
Describes the elements that make up the design, their relationships, responsibilities, and collaborations.
Doesnt describe a particular concrete design or implementation,
A pattern is like a template that can be applied in many different situations, thus, provides an abstract description of a design problem and how a general arrangement of elements (classes and objects in our case) solves it.
The consequences
The results and trade-offs of applying the pattern.
Are critical for evaluating design alternatives and for understanding the costs and benefits of applying the pattern.
Object Oriented Design Patterns
Reuse is often a factor in object-oriented design, the consequences of a pattern include its impact on a systems flexibility, extensibility, or portability
The design patterns are descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context
A design pattern names, abstracts, and identifies the key aspects of a common design structure that make it useful for creating a reusable object-oriented design
A design pattern identifies the participating classes and instances, their roles and collaborations, and the distribution of responsibilities.
Each design pattern focuses on a particular object-oriented design problem or issue. It describes when it applies, whether it can be applied in view of other design constraints, and the consequences and trade-offs of its use.
Design patterns vary in their granularity and level of abstraction. Because there are many design patterns, we need a way to organize them.
The classification helps you learn the patterns faster, and it can direct efforts to find new patterns as well
The design patterns is classified by two criteria
1. purpose, reflects what a pattern does.
2. scope, specifies whether the pattern applies
primarily to classes or to objects.
Classification of Design Patterns
Classification of design patterns
Patterns can have
either creational, structural, or behavioral purpose.
Creational patterns concern the process of object creation.
Structural patterns deal with the composition of classes or objects.
Behavioral patterns characterize the ways in which classes or objects interact and distribute responsibility.
Classification of Design Patterns
Class patterns deal with relationships between classes and their subclasses. These relationships are established through inheritance, so they are staticfixed at compile-time.
Object patterns deal with object relationships, which can be changed at run-time and are more dynamic. Almost all patterns use inheritance to some extent. So the only patterns labeled class patterns are those that focus on class relationships. Note that most patterns are in the Object scope.
Creational class patterns defer some part of object creation to subclasses, while Creational object patterns defer it to another object.
The Structural class patterns use inheritance to compose classes, while the Structural object patterns describe ways to assemble objects.
The Behavioral class patterns use inheritance to describe algorithms and flow of control, whereas the Behavioral object patterns describe how a group of objects cooperate to perform a task that no single object can carry out alone.
Design for Change
The key to maximizing reuse lies in anticipating new requirements and changes to existing requirements, and in designing your systems so that they can evolve accordingly.
To design the system so that its robust to such changes, you must consider how the system might need to change over its lifetime. A design that doesnt take change into account risks major redesign in the future. Those changes might involve class redefinition and reimplementation, client modification, and retesting.
Redesign affects many parts of the software system, and unanticipated changes are invariably expensive.
Design patterns help you avoid this by ensuring that a system can change in specific ways. Each design pattern lets some aspect of
system structure vary independently of other aspects, thereby making a system more robust to a particular kind of change.
Common Causes of Redesign
Creating an object by specifying a class explicitly.
Specifying a class name when you create an object commits you to a particular implementation instead of a particular interface. This commitment can complicate future changes.
To avoid it, create objects indirectly.
The Design patterns Abstract Factory, Factory Method, Prototype can be used to address the problems
Dependence on specific operations.
When you specify a particular operation, you commit to one way of satisfying a request.
By avoiding hard-coded requests, you make it easier to change the way a request gets satisfied both at compile- time and at run-time.
Design patterns Chain of Responsibility, Command can be used to address the problems
Common Causes of Redesign
Dependence on hardware and software platform
External operating system interfaces and application programming interfaces (APIs) are
different on different hardware and software platforms.
Software that depends on a particular platform will be harder to port to other platforms.
It may even be difficult to keep it up to date on its native platform. Its important therefore to design your system to limit its platform dependencies.
Design patterns Abstract Factory, Bridge can be used to address the problems
Common Causes of Redesign
Dependence on object representations or implementations
Clients that know how an object is represented, stored, located, or implemented might need to be
changed when the object changes
Hiding this information from clients keeps changes from cascading
Design patterns Abstract Factory, Bridge, Memento, Proxy can be used to address the problems
Algorithmic dependencies
Algorithms are often extended, optimized, and replaced during development and reuse. Objects that
depend on an algorithm will have to change when the algorithm changes
Therefore algorithms that are likely to change should be isolated. Design patterns Builder, Iterator, Strategy, Template Method, Visitor can be used to address the problems
Common Causes of Redesign
Tight coupling
Classes that are tightly coupled are hard to reuse in
isolation, since they depend on each other.
Tight coupling leads to monolithic systems, where you cant change or remove a class without understanding and changing many other classes. The system becomes a dense mass thats hard to learn, port, and maintain.
Loose coupling increases the probability that a class can be reused by itself and that a system can be learned, ported, modified, and extended more easily.
Design patterns use techniques such as abstract coupling and layering to promote loosely coupled systems; such as Abstract Factory, Bridge, Chain of Responsibility
Common Causes of Redesign
Extending functionality by subclassing
Customizing an object by subclassing often isnt easy. Every new class has a fixed implementation
overhead (initialization, finalization, etc.).
Defining a subclass also requires an in-depth understanding of the parent class. For example, overriding one operation might require overriding another. An overridden operation might be required to call an inherited operation. And subclassing can lead to an explosion of classes, because you might have to introduce many new subclasses for even a simple extension.
Object composition in general and delegation in particular provide flexible alternatives to inheritance for combining behavior. New functionality can be added to an application by composing existing objects in new ways rather than by defining new subclasses of existing classes. On the other hand, heavy use of object composition can make designs harder to understand.
Many design patterns produce designs in which you can introduce customized functionality just by defining one subclass and composing its instances with existing ones.
Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy
Common Causes of Redesign
Inability to alter classes conveniently
Sometimes you have to modify a class that cant be modified conveniently. Perhaps you need the source code and dont have it (as may be the case with a commercial class library). Or maybe any change would require modifying lots of existing subclasses.
Design patterns offer ways to modify classes in such circumstances.
Adapter, Decorator, Visitor.
How to select a Design Pattern
Design Patterns to be discussed
Object Creational Patterns
Abstract Factory Patterns
State (Object Behavioral Pattern)
Template Method (Class Behavioral Pattern)
Model-View-Controller (MVC)
Observer (Object Behavioral Pattern)
Composite (Object Structural Pattern) Strategy (Object Behavioral Pattern)
Creational Patterns
Creational design patterns abstract the instantiation process.
They help make a system independent of how its objects are created, composed, and represented.
A class creational pattern uses inheritance to vary the class thats instantiated
An object creational pattern will delegate instantiation to another object.
Abstract Factory (object creational)
Provide an interface for creating families of related or dependent objects without specifying their concrete classes
This pattern helps us to interchange specific implementations without changing the code that uses them, even at runtime
This pattern provides a way to encapsulate a group of individual factories that have a common theme. Here a class does not create the objects directly; instead, it delegates the task to a factory object.
Abstract Factory applicability
When a system should be independent of how its products are created, composed, and represented; for example, the pizza store.
When a system should be configured with one of multiple families of products; for example, different types of pizzas with different toppings
When a family of related product objects is designed to be used together, and you need to enforce this constraint; for example, a car factory
Abstract Factory Structure
Real-World Example
Suppose that we are decorating our room with two different tables: one made of wood and one made of steel. For the wooden table, we need to visit to a carpenter, and for the other table, we need to go to a metal shop. Both are table factories, so based on our demand, we decide what kind of factory we need.
In this context, you may consider two different car manufacturing companies: Honda and Ford. Honda makes models, such as CR-V, Jazz, Brio, and so forth. Ford makes different models, such as Mustang, Figo, Aspire, and so forth. So, if you want to purchase a Jazz, you must visit a Honda showroom, but if you prefer a Figo, you go to a Ford showroom.
Computer-World Example
Lets assume that we have two factories: one creates dogs and the other creates tigers; and now, you want to categorize dogs and tigers further
You may choose a domestic animal (dog or tiger) or a wild animal (dog or tiger) through these factories; so lets introduce two concrete factories: WildAnimalFactory and PetAnimalFactory, where the WildAnimalFactory is responsible for creating wild animals and the PetAnimalFactory is responsible for creating domestic animals, or pets
Illustration
AnimalFactory: An interface that is treated as the abstract factory in the following example WildAnimalFactory: A concrete factory that implements AnimalFactory interface. It creates wild
dogs and wild tigers.
PetAnimalFactory: Another concrete factory that implements the AnimalFactory interface. It creates pet dogs and pet tigers.
Tiger and Dog: Two interfaces that are treated as abstract products in this example. PetTiger, PetDog, WildTiger, and WildDog: The concrete products in the following example
interface Dog {
void speak();
void preferredAction();
interface Tiger {
void speak();
void preferredAction();
class WildDog implements Dog {
public void speak() {.
System.out.println(Wild Dog says loudly: Bow-Wow.);
public void preferredAction() {
System.out.println(Wild Dogs prefer to roam freely
in jungles.
);
class PetDog implements Dog {
public void speak() {
System.out.println(Pet Dog says softly: Bow-Wow.);
public void preferredAction() {
System.out.println(Pet Dogs prefer to stay at home.
);
class WildTiger implements Tiger {
public void speak() {
System.out.println(Wild Tiger says loudly: Halum.);
public void preferredAction() {
System.out.println(Wild Tigers prefer hunting
in jungles.
);
class PetTiger implements Tiger {
public void speak() {
System.out.println(Pet Tiger says softly: Halum.);
public void preferredAction() {
System.out.println(Pet Tigers play
in the animal circus.
);
//Abstract Factory
interface AnimalFactory {
Dog createDog();
Tiger createTiger();
//Concrete Factory-Wild Animal Factory
class WildAnimalFactory implements AnimalFactory {
public Dog createDog() {
return new WildDog();
public Tiger createTiger() {
return new WildTiger();
//Concrete Factory-Pet Animal Factory
class PetAnimalFactory implements AnimalFactory {
public Dog createDog() {
return new PetDog();
public Tiger createTiger() {
return new PetTiger();
class AbstractFactoryPatternExample {
public static void main(String[] args) {
AnimalFactory myAnimalFactory;
Dog myDog;
Tiger myTiger;
System.out.println(***Abstract Factory Demo***
); //Making a wild dog through WildAnimalFactory myAnimalFactory = new WildAnimalFactory();
myDog = myAnimalFactory.createDog();
myDog.speak();
myDog.preferredAction();
//Making a wild tiger through WildAnimalFactory myTiger = myAnimalFactory.createTiger(); myTiger.speak();
myTiger.preferredAction(); System.out.println(******************); //Making a pet dog through PetAnimalFactory myAnimalFactory = new PetAnimalFactory();
myDog = myAnimalFactory.createDog(); myDog.speak();
myDog.preferredAction();
//Making a pet tiger through PetAnimalFactory myTiger = myAnimalFactory.createTiger(); myTiger.speak();
myTiger.preferredAction();
Its important for some classes to have exactly one instance; for example,
Although there can be many printers in a system, there should be only one printer spooler; there should be only one file system and one window manager; a digital filter will have one A/D converter; an accounting system will be dedicated to serving one company.
This pattern ensures a class only has one instance and provide a global point of access to it.
How do we ensure that a class has only one instance and that the instance is easily accessible?
A better solution is to make the class itself responsible for keeping track of its sole instance. The class can ensure that no other instance can be created (by intercepting requests to create new objects), and it can provide a way to access the instance.
applicability
Use the Singleton pattern when
There must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
Structure
Real-World Example
Lets assume that you are a member of a sports team, and your team is participating in a tournament; your team needs to play against multiple opponents throughout the tournament
Before each of these matches, as per the rules of the game, the captains of the two sides must do a coin toss. If your team does not have a captain, you need to elect someone as a captain.
Prior to each game and each coin toss, you may not repeat the process of electing a captain if you already nominated a person as a captain for the team.
Basically, from every team members perspective, there should be only one captain of the team.
Computer-World Example
In some specific software systems, you may prefer to use only one file system for the centralized management of resources. Also, this pattern can implement a caching mechanism.
You notice a similar pattern when you consider the getRuntime( ) method of the java.lang.Runtime class. It is implemented as a Singleton class.
Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. The current runtime can be obtained from the getRuntime() method.
Illustration
The constructor is private, so you cannot instantiate the Singleton class(Captain) outside.
It helps us to refer the only instance that can exist in the system, and at the same time, you
restrict the additional object creation of the Captain class.
The private constructor also ensures that the Captain class cannot be extended. So, subclasses cannot misuse the concept.
The use of the synchronized keyword
So, multiple threads cannot involve in the instantiation process at the same time
It is forcing each thread to wait its turn to get the method, so thread-safety is ensured.
Note that, synchronization is a costly operation and once the instance is created, it is an additional overhead.
final class Captain {
private static Captain captain;
//We make the constructor private to prevent the use of new private private Captain() { }
public static synchronized Captain getCaptain() {
// Lazy initialization; create an object only when it is required. if (captain == null) {
captain = new Captain();
System.out
CS: assignmentchef QQ: 1823890830 Email: [email protected]
Reviews
There are no reviews yet.