OO Design

面向对象设计

译者: gaofengthucs  原作者:Gayle Laakmann
发表时间:2011-05-22 浏览量:7706 评论数:2 挑错数:0
程序员在面试过程中,遇到面向对象设计方面时,该如何应对呢?本文会给出答案。
Object Oriented Design

面向对象设计

How to Approach

如何应对

Object oriented design questions are very important, as they demonstrate the quality of a candidate’s code A poor performance on this type of question raises serious red flags.

面向对象设计的问题非常重要,它能反映出面试者的代码质量。若是对此类问题支支吾吾,面试多半就凶多吉少了。

Handling Ambiguity in an Interview 

应付面试中的含糊不清

OOD questions are often intentionally vague to test if you’ll make assumptions, or if you’ll ask clarifying questions How do you design a class if the constraints are vague? Ask questions to eliminate ambiguity, then design the classes to handle any remaining ambiguity 

面向对象设计的问题经常是有意含糊的,以此测试你是否会做假设,或者考验你是否会进一步地询问,以明确需求。否则当面对模棱两可的约束时,你又如何设计一个类呢?抛出你的问题来消除这些含糊,然后再设计类来处理剩余的含糊之处。

Object Oriented Design for Software 

面向对象设计

Imagine we’re designing the objects for a deck of cards. Consider the following approach: 1 What are you trying to do with the deck of cards? Ask your interviewer Let’s assume we want a general purpose deck of cards to implement many different types of card games 

2 What are the core objects—and what “sub types” are there? For example, the core items might be: Card, Deck, Number, Suit, PointValue 

3 Have you missed anything? Think about how you’ll use that deck of cards to imple- ment different types of games, changing the class design as necessary 

4 Now, get a little deeper: how will the methods work? If you have a method like Card Deck: getCard(Suit s, Number n), think about how it will retrieve the card 

假定要为一副扑克牌做设计,考虑下面的问题:

1. 这副牌是用来干嘛?请询问你的面官。先不妨让我们假定这副牌是通用的,可以用来玩各种不同的扑克牌游戏

2.核心对象是什么?— 其中的子类型又是什么? 比如,核心对象可能是:扑克牌,一副扑克牌,数字,花色,点值(PointValue:不知道是指什么)

3. 有遗漏的地方吗?想想看,你如何使用这副牌来实现各种不同类型的游戏?如有必要可以对类的设计做更改

4. 思考一个更深入些的问题:如何实践你的方法?如果有一个方法叫CardDeck:getCard(Suit s,Number n),实现时你又如何去获取想要的牌呢?

Object Oriented Design for Real World 

现实世界的面向对象设计

Object Real world objects are handled very similarly to software object oriented design Suppose you are designing an object oriented design for a parking lot: 

现实世界的面向对象设计与软件行业的面向对象设计很类似,假设有一个停车场,你要对此做面向对象的设计:

1 What are your goals? For example: figure out if a parking spot is taken, figure out how many cars of each type are in the parking lot, look up handicapped spots, etc 2 Now, think about the core objects (Car, ParkingSpot, ParkingLot, ParkingMeter, etc— Car has different subclasses, and ParkingSpot is also subclassed for handicapped spot) 3 Have we missed anything? How will we represent parking restrictions based on time or payment? Perhaps, we’ll add a class called Permission which handles different pay- ment systems Permission will be sub-classed into classes PaidPermission (fee to park) and FreeParking (open parking) ParkingLot will have a method called GetPermission which will return the current Permission object based on the time 4 How will we know whether or not a car is in a spot? Think about how to represent the data so that the methods are most efficient 

1.目标是什么?比如:查看停车点是否可用,查看在停车站内,每种车型的数量,查看有障碍的停车点,等等。
2.思考其中的核心对象是什么(车,停车点,停车场,计时器等---车有不同的类型,停车点也分好几种,比如有障碍的停车点)
3.有所遗漏吗?我们如何表示停车的时间和付费限制?也许我们可以添加一个Permission(许可)类,该类用于处理各种不同的付费系统。
许可类也可有多个子类,比如PaidPermission(付费停车)以及FreeParking(免费停车)。停车场会有一个GetPermission函数,可以按照时间
来返回当前的许可对象。
4.我们如何得知车辆是否在停车点?思考一下数据采取哪种表示形式,可以使得该方法最有效。

7.1 Design the data structures for a generic deck of cards Explain how you would sub- class it to implement particular card games  

7.1 请设计一个数据结构,用于一副通用的扑克。为了实现特定的扑克牌游戏,你又如何设计它的子类?

答案:


如果要实现21点游戏,我们需要知道牌的点数。JQK都是十点,A是11点(大部分情况是是这样的,但这是Hand类的工作,而不是
下面类的职责)

7.2 Imagine you have a call center with three levels of employees: fresher, technical lead (TL), product manager (PM) There can be multiple employees, but only one TL or PM An incoming telephone call must be allocated to a fresher who is free If a fresher can’t handle the call, he or she must escalate the call to technical lead If the TL is not free or not able to handle it, then the call should be escalated to PM Design the classes and data structures for this problem Implement a method getCallHandler() 

7.2 假设有一个呼叫中心,其中有三类员工:新人,技术领导(TL),产品经理(PM)。可能会有多个员工,但只有一个TL或PM。每个打进来的电话都先分配给有空的新人,当该新人无法处理电话中的事务时,他将此会叫转给技术领导,如果技术领导没空或不能处理,则电话应该分配给产品经理。请设计类和数据结构来解决此问题,实现的方法为getCallHandler()。

这三种员工都有自己的职责所在,所以这些特定的功能都跟具体的职位相关。在对应的类中,我们应该保持这种特性。

但这三种员工也有一些共性,比如他们都有家庭地址,姓名,职称,年龄等。这些属性可放在一个单独的类中,并作为父类被继承。

最后,应该有一个CallHander类,它将呼叫转移到相应的员工。

注意:对于面向对象设计的问题,可能会有很多种设计对象的方式。你应该和你的面官讨论各种方法的利弊,设计时,应该尽量考虑代码的长期灵活性和可维护性。

7.3 Design a musical juke box using object oriented principles 

7.3 请使用面向对象的方法,设计一个音乐播放机。

首先,让我们看看一套基本的系统有哪些部分
    1.CD播放器
    2.CD
    3.Display()(歌曲的播放长度,剩余时间和播放列表)

接下来,我们进行更细的分解
    1.播放列表的创建(包括添加,删除,打乱等子功能)
    2.CD选择
    3.音道选择
    4.将歌曲放入队列
    5.从播放列表中获取下一首
用户也可被引导做下面的事情:
    1.添加
    2.删除
    3.创建和编辑信息
我们如何基于对象将这些功能分类呢(哪些数据和功能结合在一起)?
面向对象设计的思路是,将数据和其相关的操作功能打包在一个单独的实体类中。


7.4 Design a chess game using object oriented principles 

7.4 请使用面向对象的方法,设计一个象棋游戏。


7.5 Design the data structures for an online book reader system  

7.5 请设计在线读书系统的数据结构

问题中没有太多功能描述,所以我们假定需要实现一个基本的在线读书系统,它具有以下功能:
1.用户创建和延续
2.寻书
3.读书
为了实现这些功能,我们可能需要其他的函数,比如获取,设置和更新等。所需的对象包括User,Book和Library.

下面的代码和面向对象设计描述了这些功能:

对于此类系统,我们做的设计是一种简化实现。我们有一个User类,用于维护所有用户相关的信息,并有一个标识符保证用户的唯一性。我们可以添加一些功能,比如用户注册,收取用户费用和设置月日的看书限额,等等

接下来,我们创建了book类,其中维护了所有书的信息。可以加入诸如add/delete/update等函数。

最后,我们创建了一个管理类,用来管理在线读书系统,它有一个监听接口,以监听任何登录请求。它也提供了图书搜索功能和展示功能。由于用户和该类会发生交互,所以搜索必须在此类中实现。

7.6 Implement a jigsaw puzzle Design the data structures and explain an algorithm to solve the puzzle  

7.6 实现一个拼图游戏,请设计用到的数据结构,并解释拼图算法

概述:
1.我们根据边的类型来将其分组。因为内边和外边相伴,反之亦然,这样我们可以直接去寻找潜在匹配。
  当我们向内走时,我们记下拼图问题的内边周长(exposed_edges),该变量初始化为角落处的边。

7.7 Explain how you would design a chat server In particular, provide details about the various backend components, classes, and methods What would be the hardest problems to solve? 

  

7.7在提供了后台的各种部件,类和方法的细节后,你 如何设计一个聊天服务程序?最难解决的问题是什么?

我们的聊天服务器是什么?

这是你和面官需要讨论的问题,不过先让我们做几个假设:设想我们实现的是一个基本的聊天服务,只支持少数几个人。
用户拥有联系人列表,可以看到朋友在线与否,它们可以发送文本信息给好友。我们不必设计群聊,语音聊天等功能。另外,需要注意到联系人列表是双向的:互为好友才能联系。一切都简化了。

那么,这个系统需要支持哪些功能呢?
1.用户A上线
2.根据当前状态,用户A请求其联系人列表
3.A的好友看到A上线了
4.A添加B到联系人列表
5.A向B发送文本消息
6.A更改状态信息或状态类型
7.A移除B
8.A下线

从这些需求中我们了解了什么?
我们必须有用户,添加请求状态,在线状态和消息等概念。

核心组件是什么?
我们需要一个存储条目的数据库,以及一个总是在线的服务程序。在服务端和客户端,我们推荐使用XML作为传输格式,因为它对于人和机器都是易读的。

核心对象和方法是什么?
下面列出了核心对象和方法,注意到我们隐藏了很多细节,比如如何将数据实际推送给客户端。


最难解决的问题是什么(或者最有趣的问题)?
1.如何获取某人是否在线---意思是,真实的获取?
用户下线时,我们希望能知道其状态,但实际上情况并非如此。用户的连接可能会断。为了确保其下线,我们通常会尝试使用ping来连接客户端。

2.如何处理不一致的信息?
内存和数据库中的信息有可能不一致,发生信息同步问题时会有什么表现?到底以那个数据为准?

3.如何使服务器可升级?
虽然我们设计的系统没有太考虑可升级性,但在实际开发中,这是一个重要的问题。我们需要将数据分布到多台服务器,如此,数据不同步的问题又会凸显出来。

4.如何防止服务器被攻击?
客户端会向我们推送数据-----如果它们向我们发动DOS系统怎么办?如何防止呢?

7.8 Othello is played as follows: Each Othello piece is white on one side and black on the other When a piece is surrounded by its opponents on both the left and right sides, or both the top and bottom, it is said to be captured and its color is flipped On your turn, you must capture at least one of your opponent’s pieces The game ends when either user has no more valid moves, and the win is assigned to the person with the most pieces Implement the object oriented design for Othello  

7.8 奥赛罗的玩法如下:每个奥赛罗一面是白色,一面是黑色。当某个奥赛罗的左右或上下被其反色的奥赛罗包围时,称它被捕获了,它需要翻过来。
在轮到你玩时,你必须捕获至少一个你对手的奥赛罗。当玩家都不能再下子时,游戏结束,赢家为拥有奥赛罗最多的一方。请使用面向对象设计来
实现奥赛罗游戏。

奥赛罗有如下主要步骤:
1. Game()为主函数,来管理游戏中的所有活动
2.构造函数对游戏进行初始化
3.获取第一个玩家的输入
4.验证输入
5.更改棋盘格局
6.检验是否有人获胜了
7.获取第二个玩家的输入

注意:奥赛罗的完整代码参见代码附件


7.9 Explain the data structures and algorithms that you would use to design an in-mem- ory file system Illustrate with an example in code where possible 

7.9 请为一个内存文件系统设计数据结构和算法,尽量结合代码讲解。

对与数据块的分配,我们可以使用位掩码数组和线性查找(参见“实际文件系统设计”)或B+树(参见维基百科)


7.10 Describe the data structures and algorithms that you would use to implement a gar- bage collector in C++ 

7.10 使用C++,实现一个垃圾回收器,并描述用到的数据结构和算法。

在C++中,使用引用技术实现垃圾回收的,基本上总是以智能指针的形式出现,它执行的就是引用计数。使用智能指针而非一般指针的原因是,
概念上的实现简洁和易于使用。

使用智能指针后,所有的垃圾回收都在后台完成---通常是在构造函数,析构函数,赋值运算符,显式对象管理函数等中出现。

有两类函数,每类都有简单:

C++的引用计数有几种实现:

1.简单引用计数


优势:性能
缺点:内存开销大,因为使用了两个指针

2.二选一的引用计数

优势:没有因为两个指针造成的内存开销
缺点:由于外加了一层,性能会有损耗

3.侵入式引用计数

优势:没有上一个的劣势
缺点:使用侵入式引用计数的类需要修改

3.所有权列表引用计数。这种方法可取代第1到第3种方法。前三种方法中,只有检验计数是否为0才是重要的---实际上具体为多少并不重要。方案4的主要思想正在于此。

给定对象的所有智能指针都存放在双链表中。智能指针的构造函数将节点添到链表,而析构函数负责从链表中移除节点,并检验链表是否为空。如果为空,则删除对象。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值