大多数人对封装的理解是封装、继承、多态,这没错,但这只是底层思维的理解。我们现在在抽象的思维层面来理解

理解隔离变化

从宏观层面来看,面向对象的构建方式更能适应软件的变化,能将变化所带来的影响减为最小。
说明:例如在上文中,使用了shape这个抽象类。一旦需求发生变化,我们不需要修改太多的代码,就可以维持一个稳定性和代码的复用性。这正是因为我们把变化都隔离到一边了,如果需求变了,修改一个地方就好了,并不需要东改改西改改。

各司其职

各司其职:

  1. 从微观层面来看,面向对象的方式更强调各个类的“责任”
  2. 由于需求变化导致的新增类型不应该影响原来类型的实现,是所谓的各负其责

怎么个各司其职?

  1. 分解思维:绘制图形的责任属于MainForm,在OnPaint中直接根据类型直接进行绘制

    1. void MainForm::OnPaint(const PaintEventArgs& e) {
    2. //针对直线
    3. for (int i = 0; i < lineVector.size(); i++){
    4. e.Graphics.DrawLine(Pens.Red,
    5. lineVector[i].start.x,
    6. lineVector[i].start.y,
    7. lineVector[i].end.x,
    8. lineVector[i].end.y);
    9. }
    10. //针对矩形
    11. for (int i = 0; i < rectVector.size(); i++){
    12. e.Graphics.DrawRectangle(Pens.Red,
    13. rectVector[i].leftUp,
    14. rectVector[i].width,
    15. rectVector[i].height);
    16. }
    17. //需求变更:添加针对圆形
    18. for (int i = 0; i < circleVector.size(); i++){
    19. e.Graphics.DrawCircle(Pens.Red, circleVector[i]);
    20. }
    21. //...
    22. Form::OnPaint(e);
    23. }
  2. 抽象思维:绘制图形的责任属于几何类型自己。如果你是Line类型,就得负责画线;如果你是矩形,就负责画矩阵。

    1. void MainForm::OnPaint(const PaintEventArgs& e){
    2. //针对所有形状
    3. for (int i = 0; i < shapeVector.size(); i++){
    4. shapeVector[i]->Draw(e.Graphics); //多态调用,各负其责
    5. }
    6. //...
    7. Form::OnPaint(e);
    8. }

各负其责其实使用的是C++中的多态机制,就是接口一样,实现不一样。就是大家都干这个事,都干draw这个事,但是我画的方式和他的不一样。如此,一个多态的机制实现了责任的分派。

对象是什么?

  1. 从语言实现层面来看,对象封装了代码和数据
  2. 从规格层面讲,对象是一系列可被使用的公共接口
  3. 从概念层面讲,对象是某种拥有责任的抽象