design patterns. properties of good design minimize complexity maintainable loose coupling...

Post on 17-Jan-2016

220 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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.1Private:

Enemy

double gravity 32.1Private:

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;

}

Exampleclass Ball

{

public:

static Ball* theBall();

tuple getPosition();

void setPosition(tuple newPosition);

private:

Sphere theSphere;

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(<0,0,1>,alpha)

Interface Segregation Principle

Solution

Triangle2D Triangle3D

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.

cPhysicsEngine cDetectCollision

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 ResHi Res

cPhysicsEngine cDetectCollision

cDetectCollisionFast cDetectCollisionSlow

Different intents: • bridge allows implementation to vary and includes adapters• strategy allows algorithms (behavior) to vary

DP hi res 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)}

DrawerprocessKeyprocessMouse

DeleteDrawerAddDrawer MoveDrawer

How about this

DrawerprocessKey

processMouse

ModeprocessMouse

DeleteAdd Move

State Design Pattern

1

supports open-close and single responsibility principles

DrawerprocessKey

processMouse

ModeprocessMouse

DeleteAdd Move

State Design Pattern

1

ModeManagerprocessKey

1 1 1

1

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

DrawerprocessKey

processMouse

ModeprocessMouse

DeleteAdd Move

1

ModeManagerprocessKey

1 1 1

1

cPhysicsEngine cDetectCollision

cDetectCollisionFast cDetectCollisionSlow

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

MouseKey Menu

Command Design Pattern

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

Widget Shape*

Triangle Line

What is the difference between a triangle and a widget holding a triangle?

Composite Design Pattern

Widget

Shape*

Triangle Line

Abstract factory

Observer Design Pattern

Observer Design Pattern

Other design patterns

wikipedia!

top related