2013-07-31 16:36:08
下面内容来自两个博客。
下面来自:张永强的BLOG http://blog.sina.com.cn/zhangyongqiang53
(摘自新浪校园招聘,网上测试)
1、面向对象相对面向过程的优点
1)结构清晰。使人们的编程与实际的世界更加接近,所有的对象被赋予属性和方法,结果编程就更加富有人性化。
2)封装性。减小外部对内部的影响。封装将对象有关的数据和行为封装成整体来处理,使得对象以外的部分不能随意存取对象的内部属性,从而有效地避免了外部错误对它的影响,大大减小了查错和排错的难度。
3)容易扩展,代码重用率高。容易扩展,在大框架不变的情况下很容易就开发出适合自己的功能,实现简单,可有效地减少程序的维护工作量,软件开发效率高。
2、面向对象相对面向过程的缺点
1)增加工作量。如果一味地强调封装,当进行修改对象内部时,对象的任何属性都不允许外部直接存取,则要增加许多没有其他意义、只负责读或写的行为。这会为编程工作增加负担,增加运行开销,并且使程序显得臃肿。
2)性能低。由于面向更高的逻辑抽象层,使得面向对象在实现的时候,不得不做出性能上面的牺牲,计算时间和空间存储大小的都开销很大。
3、举例
1)面向对象的优点举例:如象棋程序,比如我要加入悔棋的功能,如果面向过程设计的话,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了红黑双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的。
2)面向对象的缺点举例:如技术类开放问题2的留言板系统,当设计一个留言板系统,要求满足记录数每日新增10万条和查询量100万,如果每一个数据交换过程都是一个对象,那么总的性能损失将是天文数字。
张永强(答)2010年9月23日
下面来自CSDNyangzhouzhou的专栏:
A:
一、个人理解,面向对象相对于面向过程较显著的优势莫过于可扩展性、可维护性。
众所周知在软件开发过程中,开发人员与客户需要不断的沟通,而客户的需求也往往在不断的变化,软件的功能也不是一成不变的。如果采用面向过程的方法来进行软件开发,当用户需求发生变化时,比如要求修改现有软件功能的实现方式或者要求追加新的功能时,就需要自顶向下地修改模块的结构,有时候甚至整个软件系统的设计被完全推翻。
相比之下,面向对象所提供的可扩展性保证了当软件必须增加新的功能时,能够在现有系统结构的基础上,方便的创建新的子系统,而不需要改变软件系统现有的结构,也不会影响已经存在的子系统。可维护性则保证了当用户需求发生变化时,只需要修改局部的子系统的少量程序代码,而不会牵一发动全身。
举一个例子,暴雪公司开发的魔兽争霸游戏,这个游戏里面有很多人物角色,例如我们要编程实现美杜莎这个角色的技能攻击动作。如果使用面向过程的方法来实现。本例使用C++,Visual C++ 6.0环境下调试。
#include<iostream>
using namespace std;
#define SPLIT_SHOT 1
#define MYSTIC_SNAKE 2
#define MANA_SHIELD 3
void useSplitShot() //使用分裂箭技能
{
cout<<"Split Shot"<<endl;
}
void useMysticSnake() //使用秘术异蛇技能
{
cout<<"Mystic Snake"<<endl;
}
void useManaShield() //使用魔法护盾技能
{
cout<<"Mana Shield"<<endl;
}
void useSkill() //使用技能
{
int skill;
cin>>skill; //输入技能快捷键
switch(skill)
{
case SPLIT_SHOT:
useSplitShot();
break;
case MYSTIC_SNAKE:
useMysticSnake();
break;
case MANA_SHIELD:
useManaShield();
break;
default:
cout<<"无法使用技能"<<endl;
break;
}
}
int main()
{
useSkill();
return 0;
}
假如有一天玩家向暴雪反映,美杜莎这个英雄的技能太少啦,我们希望再增加一个技能。这个时候假如暴雪决定增加一个石化凝视(Stone Gaze)技能,那么需要进行以下三步:
(1) 在整个系统范围内,增加一个常量:
#define STONE_GAZE 4
(2) 在整个系统范围内增加一个新的石化凝视技能模块:
void useStoneGaze() //使用石化凝视技能
{
cout<<"Stone Gaze"<<endl;
}
(3) 在使用技能模块useSkill()内增加以下逻辑:
case STONE_GAZE:
useStoneGaze();
break;
由此可见,面向过程的开发方法制约了软件的可维护和可扩展性,模块之间的松耦合性不高,修改或增加一个模块会影响到其他的模块。
如果采用面向对象的方式,则该功能可以这样实现。本例使用Java,MyEclipse环境下调试。
Skill.java
public interface Skill //技能接口
{
void useSkill(); //使用技能
}
SplitShot.java
public class SplitShot implements Skill //分裂箭技能类
{
public void useSkill()
{
System.out.println("Split Shot"); //使用分裂箭技能
}
}
MysticSnake.java
public class MysticSnake implements Skill //秘术异蛇技能类
{
public void useSkill()
{
System.out.println("Mystic Snake"); //使用秘术异蛇技能
}
}
ManaShield.java
public class ManaShield implements Skill //魔法护盾技能类
{
public void useSkill()
{
System.out.println("Mana Shield"); //使用魔法护盾技能
}
}
SkillFactory.java
import java.util.HashMap;
import java.util.Map;
public class SkillFactory //技能工厂类
{
public static final int SPLIT_SHOT = 1;
public static final int MYSTIC_SNAKE = 2;
public static final int MANA_SHIELD = 3;
private static Map<Integer, String> skills = new HashMap<Integer, String>();
static
{
skills.put(new Integer(SPLIT_SHOT), "SplitShot");
skills.put(new Integer(MYSTIC_SNAKE), "MysticSnake");
skills.put(new Integer(MANA_SHIELD), "ManaShield");
}
public static Skill getSkill(int key)
{
try
{
String className = skills.get(new Integer(key));
return (Skill)Class.forName(className).newInstance();
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
}
Medusa.java
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Medusa //角色类——美杜莎
{
public void useSkill() throws Exception //实现美杜莎释放技能的方法
{
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
int key = Integer.parseInt(input.readLine()); //输入技能快捷键
Skill skill = SkillFactory.getSkill(key);
if(skill==null)
{
System.out.println("无法使用技能");
}
else
{
skill.useSkill();
}
}
public static void main(String[] args) throws Exception
{
new Medusa().useSkill(); //美杜莎释放技能
}
}
假设同样的情况,暴雪公司需要给美杜莎增加一个新的技能——石化凝视(Stone Gaze),那么只需要对该系统做如下修改:
(1) 增加一个石化凝视技能类StoneGaze
public class StoneGaze implements Skill //石化凝视技能类
{
public void useSkill()
{
System.out.println("Stone Gaze"); //使用石化凝视技能
}
}
(2) 在SkillFactory类中增加一个STONE_GAZE常量,并修改静态代码块。修改过的代码如下:
public static final int SPLIT_SHOT = 1;
public static final int MYSTIC_SNAKE = 2;
public static final int MANA_SHIELD = 3;
public static final int STONE_GAZE = 4;
private static Map<Integer, String> skills = new HashMap<Integer, String>();
static
{
skills.put(new Integer(SPLIT_SHOT), "SplitShot");
skills.put(new Integer(MYSTIC_SNAKE), "MysticSnake");
skills.put(new Integer(MANA_SHIELD), "ManaShield");
skills.put(new Integer(STONE_GAZE), "StoneGaze");
}
由此可见,当Medusa系统增加技能时,仅仅修改了Skill子系统,对Medusa子系统并没有任何影响。此外,Skill子系统具有良好的可扩展性,当Skill子系统需要增加新的技能时,无须修改Skill子系统的系统结构,只需要创建新的技能实现类即可。上面的例子比较简单,所以面向对象的易扩展易维护的优势体现的不太明显,但是如果随着客户提出的问题域复杂度的增加,修改面向过程软件的难度会以几何倍数增长,甚至会导致整个系统不得不推翻重做。
二、除了可扩展性和可维护性外,面向对象还具有可重用性,从而可以减少软件中的重复代码,避免重复编程。
三、面向对象中提出的对象概念更贴近现实,符合自然世界的规律,程序设计本来就是对现实世界的模拟,使用面向对象就能很自然的模拟出问题域。
四、对一个团队来说,使用面向对象思想编程,可以很容易的把项目的具体工作分离,分工合作,同时开发,从而降低了开发成本,提高了开发效率。
五、在面向过程程序中,许多重要的数据被放置在全局数据区,这样它们可以被所有的函数访问。这种结构很容易造成全局数据在无意中被其他函数改动,因而程序的正确性不易保证。面向对象程序设计的出发点之一就是弥补面向过程程序设计中的一些缺点:对象是程序的基本元素,它将数据和操作紧密地连结在一起,并保护数据不会被外界的函数意外地改变,这个就是面向对象的封装性。
以上是面向对象相对于面向过程的优点,但是面向对象也有不如面向过程之处。
一、对同一个问题域来说,面向对象程序的执行速度不如面向过程程序。在计算机速度飞速发展的今天,你可能会说,一丁点的性能牺牲没什么大不了。是的,从面向对象的角度,使的编程的结构更加清晰完整,数据更加独立和易于管理,性能的牺牲可以带来这么多的好处,没有理由不做稳赚的生意吧? 不过,在某些对速度要求极高特殊场合,例如你做的是电信的交换系统,每秒钟有超过百万的人同时进行电话交换,如果,每一个数据交换过程都是一个对象,那么总的性能损失将是天文数字。
二、面向对象程序中过多的继承属性,会导致存储问题。
不过话说回来,无论是面向对象那种如同描绘现实世界般的神奇画笔还是面向过程那种沉浸于流程和算法的脑力激荡都是我非常喜欢的,哈哈