您的位置:首页 > 编程语言 > C语言/C++

理解C++基本设计模式

2010-03-20 23:03 260 查看
一、开放封闭原则示例:
一个图形绘制函数,要求能够针对输入的不同对象,调用不同的绘制函数,如能够绘制矩形,圆形,调用相应的绘制函数。
1. 用c语言实现,这个例子其实给出了c语言模拟c++类继承的方法。利用指针的强制转换,因为指针仅仅是地址可以指向任何对象,利
用指针强制转换,告诉编译器具体按什么对象处理指针所指。
Listing 1

enum ShapeType {circle, square};

struct Shape
{
ShapeType itsType;
};
struct Circle
{
ShapeType itsType;
double itsRadius;
Point itsCenter;
};
struct Square
{
ShapeType itsType;
double itsSide;
Point itsTopLeft;
};
// 下面两个函数的实现定义在别处
void DrawSquare(struct Square*)
void DrawCircle(struct Circle*);
typedef struct Shape *ShapePointer;
void DrawAllShapes(ShapePointer list[], int n)
{
int i;
for (i=0; i<n; i++)
{
struct Shape* s = list[i];
switch (s->itsType)
{
case square:
DrawSquare((struct Square*)s);
break;
case circle:
DrawCircle((struct Circle*)s);
break;
}
}
}
这段代码用C模拟的C++的对象设计。

上面的代码不符合open close法则,因为新加入其它的shape如椭圆, DrawAllShapes函数就需要变化。
2. C++的实现
Listing 2
/*OOD solution to Square/Circle problem.*/
class Shape
{
public:
virtual void Draw() const = 0;
};
class Square : public Shape
{
public:
virtual void Draw() const;
};
class Circle : public Shape
{
public:
virtual void Draw() const;
};
void DrawAllShapes(Set<Shape*>& list)
{
for (Iterator<Shape*>i(list); i; i++)
(*i)->Draw();
}
和上面C语言实现代码对比,显然符合open close 法则,加入新的shape, DrawAllShapes函数可保持不变,只是添加新的shape内容。
二、里氏代换原则示例:
为了说明,我们先用第一种方法来看一个例子,第二种办法在另外一个原则中说明.
我们就看那个著名的长方形和正方形的例子。对于长方形的类,如果它的长宽相等,那么它就是一个正方形,因此,长方形类的对象中有一些正方形的对象。对于一个正方形的类,它的方法有setSide和getSide,它不是长方形的子类,和长方形也不会符合LSP。
  eg:
  长方形类:
  public class Rectangle{
  ...
  setWidth(int width){
  this.width=width;
  }
  setHeight(int height){
  this.height=height
  }
  }
  正方形类:
  public class Square{
  ...
  setWidth(int width){
  this.width=width;
  this. height=width;
  }
  setHeight(int height){
  this.setWidth(height);
  }
  }
  例子中改变边长的函数:
  public void resize(Rectangle r){
  while(r.getHeight()<r.getWidth){
  r.setHeight(r.getWidth+1);
  }
  }
  那么,如果让正方形当做是长方形的子类,会出现什么情况呢?我们让正方形从长方形继承,然后在它的内部设置width等于height,这样,只要width或者height被赋值,那么width和height会被同时赋值,这样就保证了正方形类中width和height总是相等的.现在我们假设有个客户类,其中有个方法,规则是这样的,测试传入的长方形的宽度是否大于高度,如果满足就停止下来,否则就增加宽度的值。现在我们来看,如果传入的是基类长方形,这个运行的很好。根据LSP,我们把基类替换成它的子类,结果应该也是一样的,但是因为正方形类的width和height会同时赋值,这个方法没有结束的时候,条件总是不满足,也就是说,替换成子类后,程序的行为发生了变化,它不满足LSP。
  那么我们用第一种方案进行重构,我们构造一个抽象的四边形类,把长方形和正方形共同的行为放到这个四边形类里面,让长方形和正方形都是它的子类,问题就OK了。对于长方形和正方形,取width和height是它们共同的行为,但是给width和height赋值,两者行为不同,因此,这个抽象的四边形的类只有取值方法,没有赋值方法。上面的例子中那个方法只会适用于不同的子类,LSP也就不会被破坏。
在进行设计的时候,我们尽量从抽象类继承,而不是从具体类继承。如果从继承等级树来看,所有叶子节点应当是具体类,而所有的树枝节点应当是抽象类或者接口。当然这个只是一个一般性的指导原则。使用的时候还要具体情况具体分析.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐