面向对象设计原则—Principles and Patterns读书笔记二

本文介绍了面向对象设计中的三大基本原则:开闭原则强调模块应对扩展开放而对修改封闭;Liskov替换原则阐述了子类应能替换其基类,并通过正方形与矩形的例子解析了该原则的重要性;依赖反转原则则提倡依赖于抽象而非具体实现。

原作者 Robert C. Martin

原文:http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf

引用页:http://www.objectmentor.com/resources/publishedArticles.html

 

二:面向对象设计原则

1 The Open-Close Principle(开闭原则)

A module should be open for extension but closed for modification.

一个模块应该对扩展开放,而对修改封闭。

这是所有OO设计原则中最重要的一条。我们应该构造这样的模块,使其不做修改即可被扩展。即我们可以在不改变模块源码的同时改变模块的行为。

多态是实现开闭原则最基本的方法。例子任何一本讲模式或者OO的书上都能找到,就不多举了。

2 The Liskov Substitution Principle(Liskov替换原则)

Subclasses should be substitutable for their base classes.Subclasses should be substitutable for their base classes.

子类应能够替代它们的基类。

这句话从语法上来说简直是句废话。在面向对象的语言中,对基类引用的场合都能够传入其子类,罕有例外。但在语义上就不一定了。看下面的例子。

class Rectangle

{

public:

void SetWidth(int width);

void SetHeight(int height);

int GetHeight();

int GetWidth();

}

void SquareTest(Rectangle& rect)

{

rect.SetWidth(5);

rect.SetHeight(6);

assert(rect.GetWidth() * rect.GetHeight() == 30);

}

上面这段测试代码无疑是任何时候都应该通过的。

从逻辑上讲,正方形是矩形的一种,是is-a的关系,因此从Rectangle类派生出Squre类似乎是顺理成章的事情。但如果上面SquareTest函数接受的是一个Square对象,assert一定会失败。这就违背了LSP。究其原因,在于Rectangle类隐含着如下假定:宽高可以被分别赋值而互不影响。

这里需要引入一个Design By Contract(按契约设计)来解释这个问题:LSP的本质是派生类必须满足基类所遵循的契约。上例中Rectangle隐含的契约:宽高可以被互不影响地赋值显然是Square做不到的。从契约角度讲,派生类必须做到如下两点:

1)前置条件不能强于基类。

2)后置条件不能弱于基类。

前置条件例:基类某个方法可以接受所有正数,而派生类覆盖了此方法,只接受大于10000的数,那么某个传1000给这个方法的调用者就会失败。

后置条件例:基类某方法返回偶数,而派生类覆盖此方法改为可返回奇数,那么对基类方法返回偶数进行校验的调用者就会失败。上例中的后置条件是设置高度不影响宽度,设置宽度不影响高度。但Square显然做不到这一点。

3 Dependency Inversion Principle (DIP)

控制反转原则

Depend Upon Abstractions. Do not depend on concretions.

如果OCP是OO的目标,那DIP就是主要的方法。DI是依赖于接口、抽象功能或抽象类的策略,而非依赖于具体功能 或类。这种原则是COM,CORBA,EJB等组件设计背后的力量。

过程式设计展现了一种特定的依赖结构。即自底向上构造软件,上层结构高度依赖于底层模块,而底层模块又依赖于更底层的模块。这种依赖关系导致了软件的脆弱。上层模块主要是处理上层策略,对下层如何实现并不关心。那为什么要上层模块直接依赖于底层实现呢?

clip_image001

而面向对象设计则展示了一种与此迥异的依赖关系。主要的依赖指向抽象。而具体实现这些抽象的模块则不再被依赖。相反,这些实现模块自身也依赖于抽象。

clip_image002

依赖抽象。依赖反转的含义很简单,所有的依赖都只应依赖于抽象,接口或抽象类。不应有任何依赖指向具体类。原因也很简单:具体类易变,而抽象类的改变则要少很多。此外,抽象类是占位符,它们代表了功能可以被改变或扩展,而抽象类自身不需更改的地方。

转载于:https://www.cnblogs.com/MichaelPeng/archive/2009/11/12/1602119.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值