Software Design Patterns

Slides:



Advertisements
Similar presentations
Welcome to. Who am I? A better way to code Design Patterns ???  What are design patterns?  How many are there?  How do I use them?  When do I use.
Advertisements

18-1 Verifying Object Behavior and Collaboration Role playing – the act of simulating object behavior and collaboration by acting out an object’s behaviors.
DESIGN PATTERNS OZGUR RAHMI DONMEZ.
Plab – Tirgul 12 Design Patterns
Patterns Reusable solutions to common object-oriented programming problems When given a programming problem, re-use an existing solution. Gang of Four.
Design Patterns Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Iterators T.J. Niglio Computer & Systems Engineering Fall 2003 Software Design & Documentation Object Behavioral.
Dept. of Computer Engineering, Amirkabir University of Tech. 1 Design Patterns Dr. Noorhosseini Introduction.
Design Patterns. What are design patterns? A general reusable solution to a commonly occurring problem. A description or template for how to solve a problem.
Visual Basic: An Object Oriented Approach 11 – Patterns in object oriented programming.
Design Patterns Module Name - Object Oriented Modeling By Archana Munnangi S R Kumar Utkarsh Batwal ( ) ( ) ( )
Design Patterns academy.zariba.com 1. Lecture Content 1.What are Design Patterns? 2.Creational 3.Structural 4.Behavioral 5.Architectural 6.Design Patterns.
1 An introduction to design patterns Based on material produced by John Vlissides and Douglas C. Schmidt.
Vrije Universiteit amsterdamPostacademische Cursus Informatie Technologie Idioms and Patterns polymorphism -- inheritance and delegation idioms -- realizing.
Design Patterns CS 124 Reference: Gamma et al (“Gang-of-4”), Design Patterns.
Design patterns. What is a design pattern? Christopher Alexander: «The pattern describes a problem which again and again occurs in the work, as well as.
05 - Patterns Intro.CSC4071 Design Patterns Designing good and reusable OO software is hard. –Mix of specific + general –Impossible to get it right the.
CS 325: Software Engineering March 17, 2015 Applying Patterns (Part A) The Façade Pattern The Adapter Pattern Interfaces & Implementations The Strategy.
An Introduction to Design Patterns. Introduction Promote reuse. Use the experiences of software developers. A shared library/lingo used by developers.
Design Patterns in Java Chapter 1 Introduction Summary prepared by Kirk Scott 1.
Introduction CS 3358 Data Structures. What is Computer Science? Computer Science is the study of algorithms, including their  Formal and mathematical.
Design Patterns CSCI 5801: Software Engineering. Design Patterns.
18 April 2005CSci 210 Spring Design Patterns 1 CSci 210.
L11-12: Design Patterns Definition Iterator (L4: Inheritance)‏ Factory (L4: Inheritance)‏ Strategy (L5: Multiple Inheritance)‏ Composite (L6: Implementation.
Software Design Patterns (1) Introduction. patterns do … & do not … Patterns do... provide common vocabulary provide “shorthand” for effectively communicating.
Computing IV Singleton Pattern Xinwen Fu.
Design Patterns CS 124 Reference: Gamma et al (“Gang-of-4”), Design Patterns.
ECE450S – Software Engineering II
Design Patterns CSIS 3701: Advanced Object Oriented Programming.
Introduction to Design Patterns. Questions What is a design pattern? Who needs design patterns? How different are classes and objects in APL compared.
CSE 332: Design Patterns Review: Design Pattern Structure A design pattern has a name –So when someone says “Adapter” you know what they mean –So you can.
Behavioral Pattern: Iterator C h a p t e r 5 – P a g e 159 Software can become difficult to manage when a variety of different traversals of a variety.
CPSC 871 John D. McGregor Module 5 Session 1 Design Patterns.
Design Patterns Solving problems with already known solutions Unit - 13.
DESIGN PATTERNS COMMONLY USED PATTERNS What is a design pattern ? Defining certain rules to tackle a particular kind of problem in software development.
Behavioral Patterns CSE301 University of Sunderland Harry R Erwin, PhD.
Sadegh Aliakbary. Copyright ©2014 JAVACUP.IRJAVACUP.IR All rights reserved. Redistribution of JAVACUP contents is not prohibited if JAVACUP.
Software Design Patterns Curtsy: Fahad Hassan (TxLabs)
Design Patterns Introduction
Design Patterns SE464 Derek Rayside images from NetObjectives.com & Wikipedia.
Interface Patterns. Adapter Provides the interface a client expects, using the services of a class with a different interface Note Avoid using object.
CS 210 Proxy Pattern Nov 16 th, RMI – A quick review A simple, easy to understand tutorial is located here:
Five Minute Design Patterns Doug Marttila Forest and the Trees May 30, 2009 Template Factory Singleton Iterator Adapter Façade Observer Command Strategy.
7 April 2004CSci 210 Spring Design Patterns 2 CSci 210.
CLASSIFICATION OF DESIGN PATTERNS Hladchuk Maksym.
Design Patterns CSCE 315 – Programming Studio Spring 2013.
1 Lecture Material Design Patterns Visitor Client-Server Factory Singleton.
Examples (D. Schmidt et al)
Chapter 0: Introduction
Unit II-Chapter No. : 5- design Patterns
Design Patterns Spring 2017.
The Object-Oriented Thought Process Chapter 15
Chapter 10 Design Patterns.
Chapter 5:Design Patterns
Software Design Patterns
MPCS – Advanced java Programming
Introduction to Design Patterns
Design Patterns Lecture part 2.
Introduction to Design Patterns
Design Patterns Based on slides provided by Abbie Jarrett
Design Patterns with C# (and Food!)
object oriented Principles of software design
Advanced Programming Behnam Hatami Fall 2017.
Software Engineering Lecture 7 - Design Patterns
Behavioral and Structural Patterns
Informatics 122 Software Design II
Design Patterns Difficult to describe abstractly Elements:
Design Patterns Part 2: Factory, Builder, & Memento
Introduction to Design Patterns
Informatics 122 Software Design II
Presentation transcript:

Software Design Patterns CSCE 315 – Programming Studio Spring 2017

What are Design Patterns? Well-known and proven solutions to common and repeating problems Really a set of standard techniques to solve frequently occurring software problems They are not really pseudocodes, rather some design solutions expressed in the form of Example codes UML diagrams In many cases, the solutions are tied to Object Oriented Programming (OOP) Although they are not limited to OOP Design patterns apply to non-Software or non-Computer Science fields as well Have to design a cable-suspended bridge on Navasota River

Motivations “We just came up with a design. Before jumping to coding it, we want to make sure that this design will actually work” “Is the problem a well-known one? If so, what is the best-known solution to this? We don’t want to reinvent the wheel if somebody else has solved this problem already” “I feel like I had to solve this same problem last semester for a different course, but cannot remember the solution” “A team-member claims that this is the best solution to the problem. But how do we know that this is really the best solution. Does this proposed solution have any flaws?” “Just wondering, if the guys in Google/Facebook/Microsoft faced the same problem that we are solving in our project? If so, what is the solution that they used? We really care about using the best design in our project”

Elements of Design Patterns Pattern Name Name to describe the pattern concisely Problem When/where to apply the solution (i.e., the pattern of the problem) Solution If the problem is a match, how to design correctly in that case

Types of Design Patterns Creational Patterns Deal with creation of objects Structural Patterns How objects/classes are composed Behavioral Patterns How classes/objects interact Other patterns for specific domains, e.g., Concurrency problems User Interface design

Creational Design Patterns Singleton Prototype Abstract Factory Factory Method Builder …

Singleton Problem: To always keep exactly 1 instance (i.e., object) of a class Trivial (or is it??) solution without much thought is following: #define INIT_VALUE 100 class MyClass{ int value; public: MyClass (int v){ value = v;} int get_value (){ return value;} void set_value (int v){ value = v;} }; MyClass* global_ptr; void square_value () { if (!global_ptr) global_ptr = new MyClass(INIT_VALUE); int val = global_ptr->get_value(); cout << "SQUARE: " << val * val << '\n'; } void double_value () { if (!global_ptr) global_ptr = new MyClass(INIT_VALUE); int val = global_ptr->get_value(); cout << "DOUBLE: " << (val + val) << '\n'; } int main () cout << "CURRENT VALUE: " << val << '\n'; square_value (); double_value ();

Singleton The proper way to solve the same problem: #define INIT_VALUE 100 class MyClass{ int value; static MyClass* instance; MyClass (int v){ value = v;} // constructor is made private!!! public: int get_value (){ return value;} static MyClass* get_instance (){ if (!instance) instance = new MyClass (INIT_VALUE); return instance; } }; MyClass* MyClass::instance = 0; //required for the instance // not for the object itself void square_value () { int val = MyClass::get_instance()->get_value(); cout << "SQUARE: " << val * val << '\n'; void double_value () cout << "DOUBLE: " << (val + val) << '\n'; int main () cout << "CURRENT VALUE: " << val << '\n'; square_value (); double_value ();

Singleton Advantages No repetition of code Other programmers do not have to worry about creating an object if one does not exist Since the constructor is private to the class, other programmers cannot create instance, even if they want to Consistency throughout

Factory Method Problem: To provide a common interface to create related objects, but let the subclasses decide which class to instantiate. class Shape{ public: virtual void draw() = 0; }; class Circle: public Shape{ void draw(){cout << "Circle\n";} class Rectangle: public Shape{ void draw(){cout << "Rectangle\n";} int main(){ vector<Shape*> shapes; int choice; while (true){ cout << "Circle(1) Rectangle(2)"; cin >> choice; if (choice == 0) break; else if (choice == 1) shapes.push_back(new Circle); else if (choice == 2) shapes.push_back(new Rectangle); } for (int i = 0; i < shapes.size(); i++) shapes[i]->draw();

Factory Method After applying the pattern: Advantage: Reduces “coupling” significantly, leading to better design Shape* Shape::make_shape (int choice) { if (choice == 1) return new Circle; else if (choice == 2) return new Rectangle; } int main(){ vector<Shape*> shapes; int choice; while (true){ cout << "Circle(1) Rectangle(2)"; cin >> choice; shapes.push_back(Shape::make_shape(choice)); for (int i = 0; i < shapes.size(); i++) shapes[i]->draw(); class Shape{ public: virtual void draw() = 0; static Shape* make_shape (int choice); }; class Circle: public Shape{ void draw(){cout << "Circle\n";} class Rectangle: public Shape{ void draw(){cout<< "Rectangle\n";}

Abstract Factory Problem/Goal: Provide an interface for creating families of related objects Example Scenario: You are designing a game, where in a particular stage, the walls are made of up of “Squares” and “Circles”. In a different stage, the walls are textured with “Rectangles” and “Ellipses” Idea: Create a series of “Squares” and “Circles” together.

Abstract Factory Example taken from sourcemaking.com class Factory { public: virtual Shape* Curved() = 0; virtual Shape* Straight() = 0; }; class SimpleShapeStage : public Factory { Shape* Curved(){return new Circle;} Shape* Straight(){return new Square;} class RobustShapeStage : public Factory { Shape* Curved(){return new Ellipse;} Shape* Straight(){return new Rectangle;} int main() { Factory* factory = new SimpleShapeStage; Factory* factory2 = new RobustShapeStage; Shape* shapes[3]; shapes[0] = factory->Curved();//Circle; shapes[1] = factory->Straight();//Square; shapes[2] = factory2->Curved(); //Ellipse; shapes[3] = factory2->Straight(); //Rectangle; for (int i=0; i < 4; i++) shapes[i]->draw(); } class Shape { public: virtual void draw() = 0; }; class Circle : public Shape { void draw() {cout << "circle\n";} class Square : public Shape { void draw() {cout << "square\n"} class Ellipse : public Shape { void draw() { cout << "ellipse\n";} class Rectangle : public Shape { cout << "rectangle\n";}

Structural Design Patterns These patterns deal with how classes and objects are composed to form larger structures Composition change at run-time rather than statically This makes these patterns powerful composition tool Unified Modeling Language (UML) is really handy to describe structural or any other patterns We will briefly see UMLs first, then explore more patterns

Unified Modeling Language (UML) A standard way to visualize the design of a system We will only learn a subset of the diagram types and notations

Structural Patterns Adapter Bridge Composite Decorator Facade Flyweight Proxy ……

Adapter Objective is to convert the interface of a class into something that the client expects Can be thought of as writing a wrapper for the adaptee A naïve approach would be to call the Adapter class directly Rather the calls go through Target, to keep the interface consistent If the Adaptee changes later on, the rest of the system is intact

Adapter - Code Example class Collection{ // Target public: void add_item (int value) = 0; int remove_item () = 0; }; // Adapter class StackCollection: public Collection{ stack<int> items; // Adaptee void add_item (int value){ items.push (value); } int remove_item (){ int val = items.top (); items.pop(); return val; int main (){ //client Collection * c = new StackCollection(); c->add_item (10); cout << c->remove_item () << endl; }

Bridge The objective is to separate abstraction from implementation Inheritance hierarchy gets complicated when abstractions and implementations are attempted to cover from the same hierarchy Has to stop this exponential growth in number of classes *images taken from sourcemaking.com

Bridge - Example

Bridge – Code Example class Circle: public Shape{ public: class DrawAPI{ public: virtual void draw_object ()=0; }; class WinDraw: public DrawAPI{ void draw_object (){cout << "In Win" << endl;} class MacDraw: public DrawAPI{ void draw_object (){cout << "In OSX" << endl;} class Shape{ protected: DrawAPI* dapi; Shape (DrawAPI* d){ dapi = d;} virtual void draw()=0; class Circle: public Shape{ public: Circle (DrawAPI* d): Shape (d){} void draw (){cout << "Circle "; dapi->draw_object();} }; class Rectangle: public Shape{ Rectangle (DrawAPI* d): Shape (d){} void draw(){cout<< "Rectangle "; dapi->draw_object();} int main () { Shape* cw = new Circle (new WinDraw); cw->draw (); Shape* rm = new Rectangle (new MacDraw); rm->draw (); }

Behavioral Patterns Iterator Interpreter Chain of Responsibility Command Mediator Memento Observer ...

Iterator Objective: Provide a way to access the elements of a collection (e.g., stack, queue, array) without exposing the underlying data structure The idea is to take traversal out of the collection and have a separate object for it Many algorithms in C++ STL are based on iterators (i.e., using iterator object) Result of Iterator: Algorithms and data structures can stay independent (i.e., decoupled) For instance, algorithms like sort, find, merge etc. can stay decoupled from data structures array, tree, linked list etc.

Iterator – Example 1 The std::sort function of STL has the following declaration: This internally uses one of Quick Sort, Merge Sort, or Insertion Sort, which are based on only the Iterators first and last Does not matter if you are sorting an array, vector, or map template <class RandomAccessIterator> void sort(RandomAccessIterator first, RandomAccessIterator last);

Iterator Example 2 class Stack { int items[10]; int sp; public: Stack(){sp = - 1;} void push(int in){ items[++sp] = in; } int pop(){return items[sp--];} friend class StackIter; StackIter *createIterator() const;}; class StackIter { const Stack *stk; int index; public: StackIter(const Stack *s){stk = s;} void first(){ index = 0;} void next(){index++;} bool isDone(){return index == stk->sp+1;} int currentItem(){return stk->items[index];} }; StackIter *Stack::createIterator()const{ return new StackIter(this); } Code taken from sourcemaking.com

Iterator Example 2 contd. bool operator == (const Stack &l, const Stack &r) { StackIter *itl = l.createIterator(); StackIter *itr = r.createIterator(); for (itl->first(), itr->first(); !itl->isDone(); itl->next(), itr->next()) if (itl->currentItem() != itr->currentItem()) break; return itl->isDone() && itr->isDone(); } Code taken from sourcemaking.com

Iterator Advantages Can add functionality beyond the ones that are supported already Does not clutter the “data structure/collection” class with different ways of accessing it Could be thought of as counteracting encapsulation, since you are giving “friend” access to the Iterator, but this enables more decoupling later on

Observer Objective: Define a one-to-many dependency between objects such that when one object changes, a number of other objects have to be updated Example: In an online Poker game, whenever somebody plays a hand, the game state in all players’ windows have to be updated Image taken from sourcemaking.com

Observer - Before Code taken from sourcemaking.com class Subject { class DivObserver { int m_div; public: DivObserver(int div){m_div = div;} void update(int val){ cout << val << " div " << m_div << " is " << val / m_div << '\n';} }; class ModObserver int m_mod; ModObserver(int mod){m_mod = mod;} cout << val << " mod " << m_mod << " is " << val % m_mod << '\n';} class Subject { int m_value; DivObserver m_div_obj; ModObserver m_mod_obj; public: Subject(): m_div_obj(4), m_mod_obj(3){} void set_value(int value){ m_value = value; notify(); } void notify(){ m_div_obj.update(m_value); m_mod_obj.update(m_value); }; Code taken from sourcemaking.com

Observer - After Code taken from sourcemaking.com class DivObserver: public Observer { int m_div; public: DivObserver(Subject *model, int div){ model->attach(this); m_div = div; } void update(int v){ cout << v << " div " << m_div << " is " << v / m_div << '\n';} }; class ModObserver: public Observer int m_mod; ModObserver(Subject *model, int mod){ m_mod = mod; } cout << v << " mod " << m_mod << " is " << v % m_mod << '\n';} class Observer{ public: virtual void update(int value) = 0; }; class Subject{ int m_value; vector m_views; void attach(Observer *obs){ m_views.push_back(obs); } void set_val(int value){ m_value = value; notify(); void notify(){ for (int i = 0; i < m_views.size(); ++i) m_views[i]->update(m_value);} Code taken from sourcemaking.com

Summary Design patterns can speed up development process when applied Help avoid design problems that might show in the later stages The difference between certain design patterns are subtle Requires paying close attention Some patterns are almost obvious Still, they are sometimes not applied and sub-optimal designs are used Make later changes difficult A common theme in all the patterns is to “Anticipate future changes” Underscores the importance of writing easy-to-change code

References Design Patterns: Elements of Reusable Object-Oriented Software by Gang of Four (GoF) http://www.sourcemaking.com