Design Patterns
Properties of good design Minimize complexity Maintainable Loose coupling Extensibility Reusability High fan in Low to medium fan out Portability Leanness Stratification Standard techniques
Some principles of good design Open-Close Principle Dependency Inversion Principle Interface Segregation Principle Single Responsibility Principle Liskov’s Substitution Principle No forgery principle (keep data in a single place) One rule one place (don’t duplicate code)
What is wrong with this picture? Ball double gravity 32.1 Private: Enemy double gravity 32.1 Private: No forgery!
How about this? Global double gravity 3.21
Why not use globals? A.They make code hard to understand. B.They make code hard to debug. C.They make code hard to modify.
Why not use globals? D.Profs O’Neill and Kuenning with haunt your dreams if you do.
Answer All of the above.
Singleton Pattern Problem: Ensure a class has only one instance and provide a global point of access to that instance.
Singleton Class class Singleton { public: static Singleton* getInstance(); private: static Singleton* theSingletonInstance; Singleton() {}; ~Singleton() {}; Singleton(const Singleton& toCopy) {}; Singleton& operator=(const Singleton& toCopy) {}; }; Singleton::Singleton* theSingletonInstance = NULL;
Instance Implementation Singleton* getInstance() { if (theSingletonInstance == NULL) theSingletonInstance = new Singleton; return theSingletonInstance; }
Example class Ball { public: static Ball* theBall(); tuple getPosition(); void setPosition(tuple newPosition); private: SpheretheSphere; Ball() {}; ~Ball() {}; tuple position; }; Ball::Ball* theBall = NULL; use: Ball* myBall = Ball::getInstance();
what I want I need a 2D graphics library that supports the following functions for triangles: –set color to r,g,b –translate vertices by dx, dy –rotate degrees about the origin –draw
what I have I have a 3D graphics library with a triangle class with the following interface –triangle() –triangle(v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z) –~triangle() –set color(r, g, b) –rotate(vector, angle) –translate(dx, dy, dz) –scale(sx, sy, sz) –draw() –flip(planeA, planeB, planeC, planeD) –texture(textureMap) –standardize()
just use the 3d class Constructor: triangle t(v1x, v1y, 0, v2x, v2y, 0, v3x, v3y, 0) Rotate: t.rotate(,alpha) Interface Segregation Principle
Solution Triangle2DTriangle3D implements the 2d triangle interface
façade Problem: You need to use a subset of a complex system or you need to interact with the system in a particular way.
what I want I want a physics engine that (among other things) detects collisions: cCollision cPhysicsEngine::detectCollision(cPath p, cTriangles t) I have a fast collision detection algorithm and a slower, more robust algorithm.
cPhysicsEngine cPhysicsFast How about this? cPhysicsSlow In the future I may want to use a super slow algorithm.
cPhysicsEnginecDetectCollision cDetectCollisionFast Strategy Design Pattern cDetectCollisionSlow supports open-close and single responsibility principles
Strategy design pattern Problem: Want to be able to swap the algorithm used in an application.
Bridge vs. Strategy Shape Drawer Low Res Hi Res cPhysicsEnginecDetectCollision cDetectCollisionFastcDetectCollisionSlow Different intents: bridge allows implementation to vary and includes adapters strategy allows algorithms (behavior) to vary DP hi res
what I want I am building a drawing program. The user enters keystrokes to change modes (Add, Delete, Move) and mouse input that is interpreted based on the current mode.
what I have global int mode; drawer.processMouse(key,position) { if mode==add processMouseAddMode(key,position) else if mode==delete processMouseDeleteMode(key,position) else if mode==move processMouseMoveMode(key,position) }
Drawer processKey processMouse DeleteDrawerAddDrawerMoveDrawer How about this
Drawer processKey processMouse Mode processMouse DeleteAddMove State Design Pattern 1 supports open-close and single responsibility principles
Drawer processKey processMouse Mode processMouse DeleteAddMove State Design Pattern 1 ModeManager processKey Mode mgr. returns pointer to correct mode
State Design Pattern Problem: want to allow an object to alter its behavior when its internal state changes
State vs. Strategy Drawer processKey processMouse Mode processMouse DeleteAddMove 1 ModeManager processKey cPhysicsEnginecDetectCollision cDetectCollisionFastcDetectCollisionSlow Different intents: state allows behaviors to vary dynamically strategy typically used when algorithm is selected at start
Problem continued I also want to support “Undo” Help!
Command MouseKeyMenu Command Design Pattern
Encapsulate a request as an object to permit logging, queuing, un-doing etc.
what I want I want a 2D drawing program that supports triangle and lines I want to be able to add, delete, draw, and move primitives. I want to be also want to be able to group primitives into a “widget” and treat the widget as a primitive. I want to be able to add and delete primitives from a widget
solution 1 WidgetShape * TriangleLine What is the difference between a triangle and a widget holding a triangle?
Composite Design Pattern Widget Shape * TriangleLine
Abstract factory
Observer Design Pattern
Other design patterns wikipedia!