专栏 | 九章算法
网址 | www.jiuzhang.com
OOD通常是应届毕业面试题,对于New Grads来说,会占整个面试评估的比例约为10-20%,可能是项目问题/算法问题的follow up,最经常出现在加面环节。大公司对OOD的考核非常注重,特别是Amazon,Google,Microsoft 和Facebook这样的大公司,像Infosys,Wipro,TCS和Cognizant这样的小型初创公司和服务公司,也非常注重这块的考核。建议new grads要充分做好OOD的知识学习和积累,这是公司考察你硬实力相当重要的一部分!
小编汇总了OOD的相关重要知识点,这些干货会更好的帮助你快速掌握OOD。
1.如何快速了解面向对象设计的整个过程?
面向对象设计的过程就是抽象的过程,分以下三步来完成:
第一步:发现类。
需求中的名词有控制台、宠物、昵称和主人等。
第二步:发现类的属性。
可作为属性的的名词有健康值、亲密度和品种等。
第三步:发现类的方法。
需求中的动词有输入、选择和领养等。
2.详细掌握OOD的基本方法与步骤
1.类的认定
OOD中关于类的认定与OOA中关于对象的认定有着密切关系。但是OOD中对类的认定,不能像OOA中那样以准确反映问题空间为衡量准则,更多的要考虑通过对类以及类层次结构的认定,寻找解空间的基本结构,并为实现提供有效的支持。以下这些准则有助于更好的认定、定义类与方法:
(1)对于问题空间中自然出现的实体,用类进行模型化;
(2)将方法设计成单用途的;
(3)如果需要对已有方法进行扩展,就设计一个新的方法;
(4)避免冗长的方法;
(5)把那些为多个方法或某个子类所需要的数据,存贮存实例变量中;
(6)为类库设计,不要只为你自己或者你目前的应用设计
复制代码
2.类的设计
在任何的面向对象应用中,类实例是系统的主要部分,而且如果采用纯面向对象的方法,那么整个系统就是由类实例组成的。因此,每个独立的类的设计对整个应用系统都有影响。在进行类的设计时,应考虑下面一些因素:
(1)类的公共接口的单独成员应该是类的操作符;
(2)类A的实例不应该直接发送消息给类B的成分;
(3)操作符是公共的当且仅当类实例的用户可用;
(4)属于类的每个操作符要么访问要么修改类的某个数据;
(5)类必须尽可能少地依赖其他类;
(6)两个类之间的互相作用应该是显式的;
(7)采用子类继承超类的公共接口,开发子类成员为超类的特化;
(8)继承结构的根类应该是目标概念的抽象模型。
复制代码
3.类层次结构的组织
OOD中类层次结构的组织与OOA采用的策略是相似的,但在涉及递增开发时将有不同。支持重用是OOD的主要任务,继承机制支持两种层次的重用。在高层设计阶段,继承性可用作泛化特化关系的建模工具。使用继承机制促进开发出有意义的高级抽象,进而有助于重用。继承关系的重用性使得设计者能够在抽象中识别一般性,并从一般产生高级抽象。通过识别这种一般性,并把它从的较高的抽象中移出来,它就在当前或今后的设计中变成可重用。
在详细设计阶段,继承性支持已有类作为新定义类的重用基础,可以把已有的部分代码复制到新子类中并修改,以适应其新的目的。继承性在已有类和新的类之间建立了一种依赖关系,子类的新代码不引起旧代码失效,继承的代码被自动地包含在新定义中,并作为新类的定义被编译。对已有的类的任何修改都被归并到下次编译的新类中。
4.类模块之间的接口技术
类之间的接口是中的一个关键,接口的方法大致有以下几类:
(1)通过继承机制实现类之间的接口
第一种方法是可定义两层或多层:描述接口的通用类以及提供各种实现的子类(例如以列表作为通用类,以堆栈,队列等作为列表的实现),从而实现同一接口,不同实现的接口方法。第二种方法使用继承机制实现类模块接口对称目的:采用几种接口到基本模块中,通过继承的正交性与输出机制来实现此方法。通用类不作输出,而多个子类执行不同的输出。例如银行的账目作为通用类,而由不同的用户来实现对它的查询。
(2)使类实例具有人工智能的状态机和主动数据结构
在定义类实现抽象数据类型及数据抽象时,将这些抽象设置于“主动”方式。也就是说,类实例不仅作为信息的被动集合,而且可看作具有内部状态及局部存储的状态机。这为类之间接口提供了有用的方法。
5.对类库和应用构架的支持
OOD的最终目标是把方法和实例变量放在类库中抽象层次尽可能高的类中,一个方法在类库的类层次结构中的层次越高,能够共享这个方法的子类就越多,以这种方式进行设计,就使重用达到了最大的可能限度。由于类库的目标是支持重用,所以纳入类库的类层次结构必须仔细加以推敲。这里主要指从有利于重用的角度来设计。尽管这方面还没有形式化的方法论,因而也没有完全自动化的工具,但可从下面3个方面着手:
(1)改善标准的协议,在面对象系统中,消息传递是对象之间通信的唯一方式,从通信的角度来看,消息的内容便是对象之间的通信协议。应提高协议的标准化程度,如:为相应的方法设计一致的接口;限制消息中的参数个数;简化方法的功能等。
(2)提高类的抽象程度,对于一个健全的类库来说,它的层次结构在进行若干层次的子类设计后,应当是深而窄的。这是因为,如果类层次结构中的层次较多。而每一层上的类少,就表明对象的共有特性经过了比较细致的分层次抽象,使用类的特殊性逐渐增强,因而能够提供较多的、在特定应用范畴内可普遍适用的类。
(3)认定和培育构架,类库中的类就象一般建筑预制件,可以复杂到整个单元居室,也可以简单到梁柱,规格比较标准,容易被独立使用。但需要应用开发人员自己根据应用特征进行组装,因此类库本身并不是重用的基本单位。相对地,构架则是以构件之间有密切的联系为特征,面向特定的应用范畴,以整个构架而不是其中的单个构件来体现它的能量,因此构架本身是重用的基本单位,一旦与应用特征相符,就可以整体被重用。所以,构架是OOD是理想的目标。
3.OOD进阶中必学的六大原则
OOD基本上有6大原则,而实际上都是互补的,也就是说一些原则需要利用另一些原则来实现自己。6大原则如下:
(1)Open-Close Principle(OCP),开-闭原则,讲的是设计要对扩展有好的支持,而对修改要严格限制。这是最重要也是最为抽象的原则,基本上我们所说的Reusable Software既是基于此原则而开发的。其他的原则也是对它的实现提供了路径。
(2)Liskov Substituition Principle(LSP),里氏代换原则,很严格的原则,规则是“子类必须能够替换基类,否则不应当设计为其子类。”也就是说,子类只能去扩展基类,而不是隐藏或覆盖基类,如有这方面需要的设计就应当参考以下两种方法替换:
(4)Interface Segregation Principle(ISP),“将大的接口打散成多个小接口”,这样做的好处很明显,这个很容易理解,不做赘述。
(5)Composition/Aggregation Reuse Principle(CARP),设计者首先应当考虑复合/聚合,而不是继承。这个就是所谓的“Favor Composition over Inheritance”,在实践中复合/聚合会带来比继承更大的利益,所以要优先考虑。
(6)Law of Demeter or Least Knowlegde Principle(LoD or LKP),迪米特法则或最少知识原则,这个原则首次在Demeter系统中得到正式运用,所以定义为迪米特法则。它讲的是“一个对象应当尽可能少的去了解其他对象”。也就是又一个关于如何松耦合(Loosely-Coupled)的法则。
4.常见面向对象设计的面试问题
问题1:用Java设计自动售货机
你需要设计一个遵循以下要求的自动售货机 接受1,5,10,25,50分钱的硬币,即便士,镍,硬币和四分之一以及1和2美元的钞票 允许用户选择产品,例如CANDY(10 ),SNACK(50),NUTS(90),可口可乐(25),百事可乐(35),苏打(45) 允许用户通过取消请求获得退款 返回所选产品和剩余更改(如果有) 允许自动售货机供应商的重置操作
问题2:设计URL缩短服务,如goo.gl
您需要设计URL缩短服务,如bit.ly或goo.gl. 您可以插入完整的URL并获得一个简短的URL。您的短网址还应记录有关访问时间的统计信息。您的系统还应该能够处理并发用户和每天数百万的URL缩短。考虑审计和簿记。
问题3:用您的编程语言设计Lift系统
电梯是至少两个电梯的组合,一个上升,另一个上下。目标是最小化用户的等待时间。如果在20层以上的高层建筑中安装电梯,请确保您的设计将如何发展。服务40层需要多少电梯,平均等待时间不少于30秒。考虑一下你的电梯的停车策略,即他们应该休息的楼层,还是应该继续上下等。
问题4:用Java或C ++设计和实现LRU缓存?
LRU缓存代表最近使用的Least。它应该从缓存中删除最近最少使用的项目,以便为新项目腾出空间。想想缓存的持久化策略。如何在崩溃后构建缓存等
问题5:为交叉点设计流量控制器系统?
您需要设计一个软件来控制交通来自四个边的交叉路口的交通信号灯。它应遵循基本的交通规则,允许行人过马路,并在合理的时间内通行。如何优化从一个方向的高流量的等待时间,例如在早晚高峰时段?
精英程序员交流社区,定期发布面试题、面试技巧、求职信息等