首先说一下,目前的编程语言实现对象时,是以哪些方式让创建对象的。1)C#等基于类型的静态语言,类型规定了对象可以具有的状态特征和行为特征,对象的一切状态和行为都是由其所属的类型确定的;这又一个很明显的好处时,我们在任何时候都知道对象的类型或接口,从而就能明确知道其数据结构,也就知道对象的状态,从而可以方便的持久化对象的状态或者重建对象;但这种为对象带来状态和行为特征的设计思路同时也有一个缺点就是对象的类型或其表现出来的接口无法更改。这点是违背“真正的对象”或者“分析阶段的对象”的特征的;2)javascript等弱类型的动态语言,这种语言认为对象无类型,对象的状态和行为不需要从类型为模板获取,状态和行为可以随时附加到某个对象上。这种思路其实很好,因为很符合上面提到的真正的对象的状态特征与行为特征的变化规律。但是这种语言也有一些致命的缺点:1)由于没有类型,导致无法在使用时明确知道其具有哪些状态和行为,这会增加编程出错的可能性,只有在运行阶段在会检测到访问了不存在的状态或行为;2)同样是弱类型的原因,对象无法被持久化,因为不知道要持久化哪些状态,同样,更不用说重建对象了;所以,基于这两个缺点,我觉得动态语言不适合在服务器端大量使用去做工程实现业务逻辑,而在一些不需要持久化对象状态的客户端环境,只在内存中处理逻辑的情况下使用这种语言比较适合;
当我们在设计软件时,如果是用C#等静态语言、基于类和接口的语言去设计对象时,该如何设计呢?在设计阶段,我觉得目标就是把分析阶段得到的对象用尽量平滑的方式转换为设计;需要把握的要点是:1)从一个基本的类创建出对象;2)用尽量平滑的设计思路去支持一个对象表现出不同类型或角色的特点;举个例子吧:
var xuehua = new Person();
xuehua.Eat(); //吃饭
var teacher = xuehua.ActAs();//扮演教师角色
teacher.Teach(); //教书xuehua这个对象首先是一个人,所以从Person这个基本类型中获取基本的状态特征和行为特征(如吃饭);然后当xuehua去教书时,他会扮演教师的角色,扮演之后他就是一个教师了,然后他就具有了教师这个角色所赋予的行为(教书)了。上面的代码看上去和真正的对象在现实生活中的变化规律类似,非常平滑;这样做有几个好处:1)强类型;2)对象交互模型与现实生活中的交互模型完全一致,所以代码非常容易懂,可读性强;3)对象不会随着参与交互场景的增多而变得臃肿和复杂,因为由于引入了角色的概念,我们将交互模型实现为对象扮演某个角色参与交互活动的方式来设计,做到了对象动态被赋予身份,从而具有与该身份相关的状态特征和行为特征;4)对象参与交互场景后所关联的一些关联信息不会直接存放在对象上,而是放在了“扮演了某个角色的对象”上,在上面的例子中就是teacher对象;
面向对象实现阶段时的对象
那么如何实现这样的设计呢?
var teacher = xuehua.ActAs();
其实很简单,可以类用装饰模式来实现,我们都知道,设计模式中的装饰模式可以动态给一个对象增加状态或行为。所以在实现阶段,我们可以设计一个Teacher类,大概设计如下:
public class Teacher : ITeacher
{
private Person actor;
public Teacher(Person actor)
{
this.actor = actor;
}
public void Teach()
{
//do the teach operation.
}
}
teacher就是实现阶段的对象,而Teacher类则是实现阶段的对象的类型;可以看到Teacher类关联了一个Person对象,同时实现了ITeacher角色接口。所以ActAs,
var teacher = xuehua.ActAs();
这个函数做的事情就是在内部创建一个Teacher类的实例,该实例对当前的Person对象有一个引用,然后返回。也许你会说,返回回来的teacher对象已经不是原来的xuehua对象了,而是一个新的对象,并且封装了xuehua这个对象;没错,所以说这是实现上的问题。我们在关注业务时,关心的不是当前对象的真正类型,而是关心对象的状态特征、行为特征,或者技术化一点来讲就是关心对象的交互模型,关心的是对象扮演什么角色在进行交互。
好了,就说这么多吧,下午要去参加知识分享。希望我的文章能带给大家一些启发。