面向对象之类的设计_代码大全笔记(二)
2012-12-12 17:46
260 查看
类的基础是抽象数据类型。抽象数据类型(ADT)是数据和对这些数据操作的集合。此“数据”为泛指,可以是窗体,文件,链表,汽车,飞机,人等。
类还支持继承和多态,因此可以认为,抽象数据类型 + 继承 + 多态 = 类
任何东西首先展示给人的都是外表,类需要一个良好的接口。(这里的接口主要是指类提供的public函数的集合)
如某个类中一半的子程序使用一部分数据,另一半的子程序使用另一部分的数据,此时可能已经把两个类混在一起了,可以考虑分开。
尽可能限制类和成员的可访问性
避免友元类
将基类数据声明为private而不是protected,以降低派生类和基类的耦合
避免在类中暴露数据成员
当决定使用继承(是一个的关系)时,考虑如下
对于每个成员函数,应该对派生类可见吗?应该有默认的实现吗?此默认实现可以被覆盖(override)吗?
对于每个数据成员,应该对派生类可见吗?
考虑子类是否需要进行向上类型转换,如果不需要,那么继承就不是正确的实现技术。-这个很关键,不需要多态时应考虑聚合
多个类共享行为而非数据,应该从共同的基类继承,在基类定义共用子程序
多个类同时共享数据和行为,应该从基类继承,并在基类中定义共用的数据和行为
当需要用基类控制接口时,使用继承;当想自己控制接口时,使用包含。
禁止隐式地产生成员函数和运算符(类似将赋值运算符声明为private的方式)
减少类所调用的不同子程序的数量(扇入扇出概念)
对其他类的子程序的间接调用尽可能少
所实例化的对象种类
在被实例化对象上直接调用的不同子程序数量
调用由其他对象返回的对象的子程序数量
为抽象对象建模(经典的shape不是真实存在的)
降低复杂度(信息隐藏,无需考虑他们了)
隔离复杂度(隔离复杂算法,大型数据等)
隐藏实现细节
限制变动的影响范围
隐藏全局数据
让参数传递更顺畅
建立中心控制点
代码更易于重用
为程序族做计划
把相关操作包装到一起
实现某种特定的重构
消除无关紧要的类
避免动词命名的类
类还支持继承和多态,因此可以认为,抽象数据类型 + 继承 + 多态 = 类
任何东西首先展示给人的都是外表,类需要一个良好的接口。(这里的接口主要是指类提供的public函数的集合)
1.合理的抽象
类的接口为隐藏具体实现而提供一种抽象,此接口应该提供一组明显相关的操作。--情非得已别让狗拿耗子1.一致的抽象层
类设计时,把类看成是实现ADT的机制,每个类只实现一个ADT,若某个类实现了多个ADT,则应把这个类重新组织为多个明确的ADT。如某个类中一半的子程序使用一部分数据,另一半的子程序使用另一部分的数据,此时可能已经把两个类混在一起了,可以考虑分开。
2.理解类所实现的抽象
一些类非常相似,需要仔细理解类的接口,以确定所需要的抽象是哪个。3.相反操作
开-关;添加-删除;激活-禁用等,设计类时,不要盲目创建相反操作,要认真考虑,是否需要。-做事情不要太顺手4.抽象性和内聚性
好的抽象通常也有很高的内聚性,如果发现某个类的内聚性很弱,不知道如何修改,可以尝试看看这个类是否表现了一致的抽象。2.良好的封装
抽象是忽略实现细节来管理复杂度,而封装是阻止看到细节。--非礼勿视1.尽可能限制成员的可访问性
如果暴露一个子程序不会破坏抽象的一致性,则这么做是可行的,否则隐藏之会更好。2.不要公开(public)数据成员
公开数据会破坏封装性,限制对抽象的控制能力。3.避免把私有的实现细节放入类的接口中
(可参考一中的隐藏抽象的实现细节一节的内容)把private段的内容放到类的头文件中还是暴露了部分的实现细节,可以把类的接口和类的实现隔离开来,在类的接口文件中声明一个指向类实现的指针。4.避免使用友元
一般情况下友元会破坏封装性,有些场合如设计模式中,使用友元是为了管理复杂度。5.让阅读代码比编写代码更方便
这个说起来容易做起来也容易,难的是一般程序员不屑于做。-这说到心坎上了6.留意过于紧密的耦合关系(两个类之间关联)
以下是一些指导建议尽可能限制类和成员的可访问性
避免友元类
将基类数据声明为private而不是protected,以降低派生类和基类的耦合
避免在类中暴露数据成员
3.类的设计和内部实现
包含(有一个的关系)才是面向对象编程的主力技术。-聚合优先于继承1.万不得已时通过private继承来实现“有一个”的关系
某些情况下根本无法包含一个对象时,可以通过private继承来实现。-private继承实际是实现继承,相当于将基类的public和protected成员以private声明于子类2.警惕有太多数据成员的类
研究表明,人们能记住的离散项目的个数是7±2。如果一个类有超过7个数据成员,可以考虑是否有必要分解为更小的类。如果数据成员是整形型者字符串这类简单数据类型,可以按7±2上限考虑,若是复杂对象,则按7±2下限考虑。-这个是否有点绝对化了,看到好多类都是超过这个数的,应该要视情况而言吧当决定使用继承(是一个的关系)时,考虑如下
对于每个成员函数,应该对派生类可见吗?应该有默认的实现吗?此默认实现可以被覆盖(override)吗?
对于每个数据成员,应该对派生类可见吗?
1.public继承实现“是一个......”的关系
如果派生类不准备完全遵守基类定义的同一个接口契约,就不应该用继承。考虑子类是否需要进行向上类型转换,如果不需要,那么继承就不是正确的实现技术。-这个很关键,不需要多态时应考虑聚合
2.遵循Liskov替换原则
3.派生类的成员函数不要与基类中不可覆盖的成员函数重名
如果一个函数在基类中是私有的,派生类就不要创建一个同名的成员函数。4.公用的接口,数据放到继承树中尽可能高的位置
多高算高?当把子程序移到更高层次会破坏抽象性,就该停手。5.派生类覆盖某个子程序,其中没做任何操作,这种情况需要注意
6.避免让继承体系过深
7.尽量使用多态,避免大量的类型检查
8.让所有数据都是private,而非protected
当决定使用多重继承之前,应该仔细考虑其他解决方案。何时使用继承,何时使用包含
多个类共享数据而非行为,应该创建这些类可以包含的共用对象多个类共享行为而非数据,应该从共同的基类继承,在基类定义共用子程序
多个类同时共享数据和行为,应该从基类继承,并在基类中定义共用的数据和行为
当需要用基类控制接口时,使用继承;当想自己控制接口时,使用包含。
成员函数和数据成员
让类中子程序尽可能少禁止隐式地产生成员函数和运算符(类似将赋值运算符声明为private的方式)
减少类所调用的不同子程序的数量(扇入扇出概念)
对其他类的子程序的间接调用尽可能少
尽量减小类与类之前相互合作的范围
尽量让下面的数字最小所实例化的对象种类
在被实例化对象上直接调用的不同子程序数量
调用由其他对象返回的对象的子程序数量
4.创建类的原因
为现实世界中的对象建模为抽象对象建模(经典的shape不是真实存在的)
降低复杂度(信息隐藏,无需考虑他们了)
隔离复杂度(隔离复杂算法,大型数据等)
隐藏实现细节
限制变动的影响范围
隐藏全局数据
让参数传递更顺畅
建立中心控制点
代码更易于重用
为程序族做计划
把相关操作包装到一起
实现某种特定的重构
5.应该避免的类
避免创建万能类消除无关紧要的类
避免动词命名的类
相关文章推荐
- 面向对象之子程序的设计及防御编程_代码大全笔记(三)
- 面向对象之数据抽象_代码大全笔记(一)
- 面向对象设计之代码复用
- C#面向对象设计模式学习笔记(8) - Composite 组合模式(结构型模式)
- OC面向对象思想,类和对象的关系,类的设计笔记
- 面向对象设计模式纵横谈:Factory Method 工厂方法模式(笔记记录)
- C#面向对象设计模式学习笔记(7) - Bridge 桥接模式(结构型模式)
- 【代码总结】PHP面向对象之类与对象
- PHP面向对象学习笔记之二 生成对象的设计模式
- 设计模式学习笔记二:面向对象基础二
- 设计模式学习笔记二:面向对象基础五之集合和泛型
- 面向对象设计模式纵横谈:Abstract Factory 抽象工厂模式(笔记记录)
- 笔记:面向对象设计原则
- Builder生成器(创建型设计模式)面向对象设计模式纵横谈讲座笔记之四
- 面向对象设计模式纵横谈:Singelton单件模式(笔记记录)
- 面向对象设计模式纵横谈:Adapter 适配器模式(笔记记录)
- 面向对象设计模式纵横谈:Bridge 桥接模式(笔记记录)
- 读代码大全二笔记之关于设计启发得总结
- 面向对象设计与模式与原则--面向对象设计模式纵横谈讲座笔记之一
- PHP面向对象学习笔记之二:生成对象的设计模式