高内聚原则(High Cohesion Principle)
(1)问题
怎样使得复杂性可管理?
(2)方案
分配一个职责,使得保持高内聚。
(3)分析
内聚是评价一个元素的职责被关联和关注强弱的尺度。如果一个元素具有很多紧密相关的职责,而且只完成有限的功能,则这个元素就具有高内聚性。此处的元素可以是类,也可以是模块、子系统或者系统。
在一个低内聚的类中会执行很多互不相关的操作,这将导致系统难于理解、难于重用、难于维护、过于脆弱,容易受到变化带来的影响。因此我们需要控制类的粒度,在分配类的职责时使其内聚保持为最高,提高类的重用性,控制类设计的复杂程度。为了达到低内聚,我们需要对类进行分解,使得分解出来的类具有独立的职责,满足单一职责原则。在一个类中只保留一组相关的属性和方法,将一些需要在多个类中重用的属性和方法或完成其他功能所需的属性和方法封装在其他类中。类只处理与之相关的功能,它将与其他类协作完成复杂的任务。
示例
public class Genetic {
public Genetic(int s, int n, int g, float c, float m, frmGa f) {
//
}
// 初始化GA算法类
public void Init(int[] x, int[] y) {
//
}
// 初始化种群
private void InitGroup() {
//
}
private int Evaluate(int[] chromosome) {
//
}
// 计算种群中各个个体的累积概率,前提是已经计算出各个个体的适应度fitness[max],
// 作为赌轮选择策略一部分,Pi[max]
private void CountRate() {
//
}
// 挑选某代种群中适应度最高的个体,直接复制到子代中
// 前提是已经计算出各个个体的适应度Fitness[max]
private void SelectBestGh() {
//
}
// 复制染色体,k表示新染色体在种群中的位置,kk表示旧的染色体在种群中的位置
private void CopyGh(int k, int kk) {
//
}
// 赌轮选择策略挑选
private void Select() {
//
}
// 进化函数,正常交叉变异
private void Evolution() {
//
}
// 进化函数,保留最好染色体不进行交叉变异
private void Evolution1() {
//
}
// 类OX交叉算子
private void OXCross(int k1, int k2) {
//
}
// 交叉算子,相同染色体交叉产生不同子代染色体
private void OXCross1(int k1, int k2) {
//
}
// 多次对换变异算子
private void OnCVariation(int k) {
//
}
public void Solve() {
//
}
}
以上代码片段摘自TspGA(部分命名和访问修饰符有修改),这是用C#写的非常著名的用遗传算法解决旅行家问题的方案。部分实现代码限于篇幅已被省略,Genetic类是用来封装遗传算法的类,所有和遗传算法相关的内部全部被封装进这个类,符合高内聚原则,同时也符合信息专家原则。不过最终这个类中的代码有600行之多,可能会让人觉得代码的可维护性不高,甚至对这个类是否符合单一职责原则产生怀疑。变异概率和交叉因子的选择是否可以另起2个类来封装呢?
通用职责分配软件原则考虑的是职责的封装问题,高内聚原则鼓励将具有高度相关性的职责封装在一个类中,该案例将所有和遗传算法相关的职责封装进一个类中的做法我认为没有问题,即使它可能存在多个引起它变化的原因。所以我个人认为高内聚原则和单一职责原则并没有显著冲突,要看设计者的选择。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/69396.html