大多数人对封装的理解是封装、继承、多态,这没错,但这只是底层思维的理解。我们现在在抽象的思维层面来理解
理解隔离变化
从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小。
说明:例如在上文中,使用了shape这个抽象类。一旦需求发生变化,我们不需要修改太多的代码,就可以维持一个稳定性和代码的复用性。这正是因为我们把变化都隔离到一边了,如果需求变了,修改一个地方就好了,并不需要东改改西改改。
各司其职
各司其职:
- 从微观层面来看,面向对象的方式更强调各个类的“责任”
- 由于需求变化导致的新增类型不应该影响原来类型的实现,是所谓的各负其责
怎么个各司其职?
分解思维:绘制图形的责任属于MainForm,在OnPaint中直接根据类型直接进行绘制
void MainForm::OnPaint(const PaintEventArgs& e) {
//针对直线
for (int i = 0; i < lineVector.size(); i++){
e.Graphics.DrawLine(Pens.Red,
lineVector[i].start.x,
lineVector[i].start.y,
lineVector[i].end.x,
lineVector[i].end.y);
}
//针对矩形
for (int i = 0; i < rectVector.size(); i++){
e.Graphics.DrawRectangle(Pens.Red,
rectVector[i].leftUp,
rectVector[i].width,
rectVector[i].height);
}
//需求变更:添加针对圆形
for (int i = 0; i < circleVector.size(); i++){
e.Graphics.DrawCircle(Pens.Red, circleVector[i]);
}
//...
Form::OnPaint(e);
}
抽象思维:绘制图形的责任属于几何类型自己。如果你是Line类型,就得负责画线;如果你是矩形,就负责画矩阵。
void MainForm::OnPaint(const PaintEventArgs& e){
//针对所有形状
for (int i = 0; i < shapeVector.size(); i++){
shapeVector[i]->Draw(e.Graphics); //多态调用,各负其责
}
//...
Form::OnPaint(e);
}
各负其责其实使用的是C++中的多态机制,就是接口一样,实现不一样。就是大家都干这个事,都干draw这个事,但是我画的方式和他的不一样。如此,一个多态的机制实现了责任的分派。
对象是什么?
- 从语言实现层面来看,对象封装了代码和数据
- 从规格层面讲,对象是一系列可被使用的公共接口
- 从概念层面讲,对象是某种拥有责任的抽象