传统的面向过程的程序设计(Procedure Oriented Programming, POP)采用特定语句或指令序列给出问题求解过程,也就是在设计过程中主要考虑如何把问题的解决步骤用合适的语句或指令进行描述。采用面向过程的语言进行软件设计时,以过程为中心,一般采用自顶向下、逐步求精的设计方式,把一个复杂的大型问题分解成多个简单的小型问题,而各个问题的解决步骤又可以采用功能函数去具体实现,系统以各种函数的调用方式进行组织。典型的面向过程的语言有C、Pascal和Fortran等语言。

举个游戏中战士角色的设计案例,若采用C语言进行设计,代码如下所示。战士角色用结构体进行定义,内部含有描述名字、生命值和金钱的属性;同时定义三个功能函数,分别实现战斗、治疗和工作处理。
struct Hero{ //战士
char* name; //名字
int life; //生命值
int money; //金钱
};
void fight(Hero h, int lValue, int mValue){ //战斗
h.life-= lValue; //消耗生命值
}
void treat(Hero h, int lvalue, int mValue){ //治疗
h.life+=lvalue; //增加生命值
h.money-=mValue; //消耗金钱
}
void work(Hero h, int mValue){ //工作
h.money+=mValue; //增加金钱
}
从代码上看,战士角色的属性和功能是分离的,功能函数需要传入战士的变量以便对其属性进行操作。而由于属性值没有任何保护措施,只要调用功能函数就可以对给定战士的属性进行操作,存在着安全隐患。假设需要增加一种叫特种战士的角色,要求该角色增加了一个是伪装状态的属性,那么需要重新定义一个新角色。原有的功能函数由于传入的角色参数类型改变了,因此需要重新定义,以下仅给出战斗功能函数的定义。此外增加了改变伪装状态的功能定义。
struct HeroSpecial{ //特种战士
char* name;
int life;
int money;
boolean disguised; //是否伪装
};
void fightS(HeroSpecial h, int lValue, int mValue){ //战斗
h.life- = lValue; //消耗生命值
}
……
void change(HeroSpecial h, boolean beDisguised){ //改变伪装
h. disguised = beDisguised;
}
由以上代码可见,为了获得一个类似的角色和相似的功能,需要增加大量代码,相同功能的代码却难以复用。随着软件系统的规模的扩大和功能的复杂化,大量的函数调用使得软件体系错综复杂,造成了软件开发和维护方面的难度不断增大,在软件的成本提高的同时,可靠性却往往难以保证。
面向对象程序设计(Object Oriented Programming, OOP)是一种全新的编程范式,该范式以对象世界的思维方式考虑问题,尽可能以自然的方式来描述问题的解决方案。上世纪60年代,针对传统面向过程的设计过程中,由于数据和处理数据的过程相互独立,导致在设计大型系统时面临系统的复杂度大大提升的问题,图灵奖得主Alan Kay首先提出了面向对象的设计思路,同时设计了一款名为Smalltalk的编程语言支持这种先进的设计。Alan Kay也因在面向对象设计领域的先驱性贡献而被誉为“面向对象之父”。Alan Kay描述的面向对象编程的主要特点包括:
(1)万物皆对象。程序中的对象(object)是一种特殊的变量,既可以存储数据,也可以对自身进行各种操作。
(2)程序由对象组成。程序中各个对象之间通过发送消息来实现功能方法的调用。
(3)每个对象都有自己的存储空间,可以由其他对象组合而成。复杂的系统可以由简单的对象组成。
(3)每个对象都有类型(class)。对象是特定类型的实例(instance);类型是对具有相同属性和行为的对象集合的概念描述。
(4)给定类型的所有对象可以接收同样的信息。
当前许多主流的语言是面向对象的编程语言,例如Java、C++和C#等。若采用Java语言,以面向对象的方式实现上文所述游戏角色的设计,代码如例1所示。
【例1】 利用Java设计游戏角色
public class Hero { //战士
private String name; //名字
private int life; //生命值
private int money; //金钱
public void fight(int lifeValue){//战斗
life- = lifeValue;
}
public void treat(int lifeValue, int moneyValue){ //治疗
life+ = lifeValue;
money- = moneyValue;
}
public void work(int moneyValue){ //工作
money+ = moneyValue;
}
}
class HeroSpecial extends Hero { //特种战士
private boolean disguised; //是否伪装
public void change(boolean beDisguised){ //改变伪装
disguised = beDisguised;
}
}
该程序中给出了战士角色和特种战士角色的相应设计,分别用Hero和HeroSpecial这两个类进行描述。类中的属性和功能方法均带有private或public等称为访问权限控制的关键字修饰,可以在语言层面设置对变量和方法的保护级别。类中的功能方法可直接对类中的属性进行操作,无需传递参数。HeroSpecial类采用继承Hero类的方式进行概念扩展,增加了一个disguised属性和一个change()方法,而Hero类中原有的属性(包括name、life和money)和方法(包括fight()、treat()和work())可以直接被HeroSpecial类所复用,而无需重新定义。由此可见面向对象的设计方式可以更好地满足简化开发、安全控制以及代码复用等需求,具有优越的可扩展性。
参考资料:陈荣鑫. Java编程精要[M]. 北京:清华大学出版社,2024.8.
1614

被折叠的 条评论
为什么被折叠?



