敏捷软件开发 原理、模式与实践 读书笔记

(1)单一职责原则(SRP)

就一个类而言,应该仅有一个引起它变化的原因。

(2)开发-封闭原则(OCP)

软件实体(类、模板、函数等)应该是可以扩展的,但是不可修改的。

即对扩展开发,对更改封闭。

实例说明:Shape应用程序

①违反OCP










③问题:如果所有圆必须在正方形之前绘制,那么该怎么处理呢?













实例代码:


注意:关于typeid的错误(warning C4541: 'typeid' used on polymorphic type 'class A' with /GR-; unpredictable behavior may result) 


可能在写程序用到typeid的时候遇到这种警告
运行的时候就会出现致命错误


解决方法:在vc6中. 


Project - settings... - C/C++ 


在Category那里选 C++ Language 


再在下边勾上 Enable Run-Time Type Information[RTTI]

//shap.h

#ifndef _SHAPE_H
#define _SHAPE_H
#include <typeinfo>
#include <string>
#include <iostream>
using namespace std;


class Shape
{
public :
virtual void Draw() = 0 ;
bool Precedes(const Shape &)const;
bool operator<(const Shape & s)const
{
return Precedes(s);
}
  
private :
static const char * typeOrderTable[];
} ;

#endif

//shape.cpp


#include "Shape.h"
#include "Circle.h"
#include "Square.h"
#include <iostream>
using namespace std;


const char* Shape::typeOrderTable[] =
{
typeid(Circle).name(),
    typeid(Square).name(),
0
};
bool Shape:: Precedes(const Shape & s) const
{




const char * thisType = typeid(*this).name();
const char * argType = typeid(s).name();
bool done = false ;
int thisOrd = -1 ;
int argOrd = -1 ;


for ( int i = 0 ; !done ; i++)
{
const char * tableEntry = typeOrderTable[i] ;


if(tableEntry != 0 )
{
if(strcmp(tableEntry,thisType)==0)
thisOrd = i ;
if(strcmp(tableEntry,argType)==0)
argOrd = i ;
if( ( argOrd >=0) && ( thisOrd >= 0 ))
done = true ;
}
else //tableEntry == 0
done = true ;


}
return thisOrd < argOrd ;
//return (thisOrd < argOrd) ;
}



//Circle.h

#ifndef _CIRCLE_H

#define _CIRCLE_H

#include "Shape.h"


class Circle: public Shape
{
private:
int r;
public : void Draw();
};

#endif


//Circle.cpp

#include "Circle.h"
#include <iostream>
using namespace std;
void Circle::Draw()
{
cout<<"画一个圆\n"<<endl;
}


//squaer.h 和square.cpp和Circle.h和Circle.cpp类似


//test.cpp


#include "Shape.h"
#include "Circle.h"
#include "Square.h"
#include <iostream>
#include<vector>
#include <algorithm>
using namespace std;








template <typename P>
class Lessp
{
public :
bool operator()(const P p, const P q ){ return (*p) < (*q);}
};


void DrawAllShapes(vector<Shape *>&list)
{
vector<Shape*> orderedList = list ;
sort(orderedList.begin(),
orderedList.end(),
Lessp<Shape*>());


vector<Shape*>::const_iterator i;
for(i=orderedList.begin() ; i!=orderedList.end();i++)
{
(*i)->Draw();


}


}




void main()
{
vector<Shape*> list ;
Shape *c1= new Circle();
Shape *c2= new Circle();
Shape *c3= new Circle();
Shape *s1= new Square();
Shape *s2= new Square();
Shape *s3= new Square();


list.push_back(c1);
list.push_back(s2);
list.push_back(s1);
list.push_back(c2);
list.push_back(s3);
list.push_back(c3);


DrawAllShapes(list);


}

运行结果




(3)Liskov替换原则(LSP)

子类型必须能够替换掉它们的基类型。

启发式规则和习惯用法:

其一:完成的功能少于其基类的派生类通常是不能替换其基类的,因此就违反了LSP。如下

public class Base

{

public void f(){/**some code */}


}

public class Derived extends Base

{

public void f(){}

}

其二:在派生类的方法中添加了其基类不会抛出的异常。


(4)依赖倒置原则

抽象不应该依赖于细节,细节应该依赖于抽象。













模板方法的缺点:

HEADER 和THERMOMETER的类型不能在运行时更改;

对于新类型的HEADER 或者THERMOMETER的使用会迫使重新编译和重新部署。所以除非有非常严格的速度性能要求,否则应优先使用动态多态性。


(5)接口隔离原则(ISP)
















  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值