剪刀剪纸
面向对象是个理论概念,理解起来比较抽象,很难定义一个标准衡量做到什么程度就是面向对象了,很多人认为只要有对象实体类就是了,我倒是觉得如果只是那样的话,把这些对象认定是一个特殊的数据类型时,看起来有可能就成为面向过程了。当然,面向过程也有其优点和适用场景。
剪刀剪纸,如果是简单的用程序表述,用剪刀把纸剪开了,这是在描述一个过程,就算有剪刀的对象和纸的对象,我觉得这也不能算是面向对象。面向对象应该是模拟里现实的场景,让对象以符合现实的形式抽象的工作,剪刀剪纸然后纸裂开了。这里忽略了使用剪子的人,因为业务并不需要关心谁用了剪子。
首先,剪子只需要关心自己发出了剪的动作,因为它只有剪的职责,在现实世界中,剪刀就是剪子,只能剪,剪任何能剪的东西,和纸不沾边的独立存在着。
interface ICut { void Cut(Thing thing); } public class Scissors : ICut { public void Cut(Thing thing) { throw new NotImplementedException(); } }
纸是能剪的东西,所以:
public class Thing { public void Stressed() { } } public class Paper : Thing { }
这里东西使用Stressed(受力),因为它需要关心自己是不是被剪了,当然,业务只关心是否是被剪,也可以直接用be cut之类的
剪子要告诉Thing,我发出了多大力度,所以这个场景中的Thing需要关注自身承受了多大力:
public int PotencyDimension { get; set; }
public void Cut(Thing thing) { thing.PotencyDimension = 2; }
这时,Thing要判断一下自身是否能承担,可以将判断规则独立出来,这样,所有被剪的东西都可以使用这条规则,也可以根据提供规则的重写,或者以后了解契约式编程,这里就不说了
protected virtual bool CanBear() { bool isBear = false; if (Hardness > PotencyDimension) { isBear = true; } return isBear; } public void Stressed() { if (CanBear()) { } }
也可以提供重写Stressed,如果剪子剪土块的时候就是崩散开,剪树枝就是断开什么的。。。
上面的代码已经表示出了大概意思,剪只管剪,开不开是不管的,剪和开分别属于不同的对象,每个对象只管自己的职责,各个对象各司其责,互相协作而成为一个系统,这才是面向对象。
最后,被抽象掉的使用剪子的人什么的。。。,代码就不编了,因为抽象掉了,所以人发出来的力没有对象可依靠,但是属于不可或缺的源动力,对业务很关键,但又不好放到Thing和Scissors中的,就可以归为一类,DDD原书上是把这类动作称为Service。