Showing posts with label DESIGN PATTERN. Show all posts
Showing posts with label DESIGN PATTERN. Show all posts

Wednesday, August 29, 2007

Liskov's Substitution Principle(LSP)

0 comments;Click here for request info on this topic
Motivation

There are situations when we design a program module and we create some class hierarchies. Then we extend some classes creating some derived classes.

When the new classes are used it assumed that they just extend without replacing the functionality of old classes. Otherwise the new classes can produce undesired effects when they are used in existing program modules. This is just a particularization of the Open Close Principle.

Likov's Substitution Principle states that if a program module is using a Base class, then the reference to the Base class can be replaced with a Derived class without affecting the functionality of the program module.

Intent

Derived types must be completely substitutable for their base types.

Example

Below is the classic example for which the Likov's Substitution Principle is violated. In the example 2 classes are used: Rectangle and Square. Let's assume that the Rectangle object is used somewhere in the application. We extend the application and add the Square class. The square class is returned by a factory based on some conditions and we don't know the exact what type of object will be retuned. But we know it's a Rectangle. We get the rectangle object, set the width and height and get the area. But surprise!! This is not the expected result.

class Rectangle

{

protected int m_width;

protected int m_height;

public void setWidth(int width){

m_width = width;

}

public void setHeight(int height){

m_height = height;

}

public int getWidth(){

return m_width;

}

public int getHeight(){

return m_height;

}

public int getArea(){

return m_width * m_height;

}

}

class Square extends Rectangle

{

public void setWidth(int width){

m_width = width;

m_height = width;

}

public void setHeight(int height){

m_width = height;

m_height = height;

}

}

class LspTest

{

private static Rectangle getNewRectangle()

{

// it can be an object returned by some factory ...

return new Square();

}

public static void main (String args[])

{

Rectangle r = LspTest.getNewRectangle();

r.setWidth(5);

r.setHeight(10);

// user knows that r it's a rectangle. It assumes that he's able to set the width and height as for the base class

System.out.println(r.getArea());

// now he's surprised to see that the area is 100 instead of 50.

}

}

Read full story

ABATRACT FACTORY DESIGN PATTERN

0 comments;Click here for request info on this topic
Basic conceptualization through source code.


#include

//#define SIMPLE

#define ROBUST

class Shape

{

public:

Shape() { id_ = total_++; }

virtual void draw() = 0;

protected:

int id_;

static int total_;

};

int Shape::total_ = 0;

class Circle : public Shape

{

public:

void draw() { cout << "circle " <<>

};

class Square : public Shape

{

public:

void draw() { cout << "square " <<>

};

class Ellipse : public Shape

{

public:

void draw() { cout << "ellipse " <<>

};

class Rectangle : public Shape

{

public:

void draw() { cout << "rectangle " <<>

};

class Factory

{

public:

virtual Shape* createCurvedInstance() = 0;

virtual Shape* createStraightInstance() = 0;

};

class SimpleShapeFactory : public Factory

{

public:

Shape* createCurvedInstance() { return new Circle; }

Shape* createStraightInstance() { return new Square; }

};

class RobustShapeFactory : public Factory

{

public:

Shape* createCurvedInstance() { return new Ellipse; }

Shape* createStraightInstance() { return new Rectangle; }

};

void main()

{

#ifdef SIMPLE

Factory* factory = new SimpleShapeFactory;

#else ROBUST

Factory* factory = new RobustShapeFactory;

#endif

Shape* shapes[3];

shapes[0] = factory->createCurvedInstance(); // shapes[0] = new Ellipse;

shapes[1] = factory->createStraightInstance(); // shapes[1] = new Rectangle;

shapes[2] = factory->createCurvedInstance(); // shapes[2] = new Ellipse;

for (int i=0; i <>

shapes[i]->draw();

}

Read full story