关于单一职责原则的一点理解

本文深入分析了单一职责原则在图形类设计中的应用,通过对比不同设计方案,探讨了如何使得类及其子类最大程度地反映现实世界中的事物,同时保持代码的清晰性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

          写这篇博文,是因为在论坛里看到了一篇有关这一话题的帖子,产生了一些想法,自知记忆力较差,便急切的想找到个地方记录下来,以便日后温故。

          我所说的帖子的地址是http://topic.youkuaiyun.com/u/20110120/12/4ee6335d-247d-4c1f-8c9d-8d70f44ddaba.html

          提问者提出了这样的问题:

          Shape是抽象基类,Triangle和Rectangle继承自Shape,Draw()、SaveToXml()、LoadFromXml()是三个虚函数。
按照SRP(单一职责原则),把这三个虚函数放在一个类中,是否不好?应该怎么做?分别创建三个子类去实现?

class Shape{
public:
virtual Draw()=0;
virtual SaveToXml()=0;
virtual LoadFromXml()=0;
};

class Triangle public: Shape{
...
};

class Rectangle public: Shape{
...
};


个人认为8楼的解答最给力:

class Shape{
public:
virtual Draw()=0;

};

class XmlPersist
{public:
virtual SaveToXml()=0;
virtual LoadFromXml()=0;
};

class Triangle public: Shape , public XmlPersist{
...
};

class Rectangle public: Shape , public XmlPersist {
...
};


          现在,说说我对这个问题的理解。

          人们通常认为,之所以要坚持这样的一个原则,目的是要一个类只做一件事情。可是怎么样的事情才算是一件事情呢?考试算是一件事情么?如果算,那么考试中还包含了复习,准备考试用具,答题,交卷子等一系列的事情,这样想来考试算是一件事情么?

          更深奥的解释是,让一个类只有一个可以引起它变化的原因。这样的解释就更让人难以理解了,软件概念如此复杂,如此多变,所谓的这一个引起变化的原因到底是指一种情况,还是一个因素亦或是一个条件?

           为什么一个类的职责不宜过多?有人会说那样在使用或修改时会遇到麻烦,可是为什么一个类的职责过多时就会导致修改或使用时遇到麻烦呢?这里的职责又是什么概念?一个函数代表一个职责么?还是一个类代表一个职责?还是一个模块代表一个职责?

           我想起《人月神话》中的一句话,开发软件的主要根本任务是打造抽象软件实体的复杂概念结构。我这样理解这句话:人,通过一系列手段和方法将现实生活中的事物映射成复杂的软件概念,在这个映射的过程中,我们采取各种各样的设计模式,各种原则,无非是想使映射后的软件概念最大限度的反应真实的事物。

           我之所以人为8楼的答案最给力,并不是因为他的方法符合了职责单一性原则,而是在于我人为他的方法最大程度的反应了真实的事物(事实上我现在仍不理解单一职责)。

          问一问自己,什么是Shape?当你只考虑什么是Shape的时候,你会考虑到读取文件么?当你只考虑打开一个XML文件,写一个XML文件时,你会考虑到Shape么?Shape本身和XML文件,这两者之间本身没有任何关系。从根本上讲,他们完全是两个不同的问题域里的东西。你也许会说,他们之间终究是有联系的呀,错,他们之间没有任何联系,你所说的联系是软件概念中的联系,我所说的没有联系,是现实世界中的联系。可如果我们让他们在软件概念中仍和现实世界中一样,没有任何联系,那么似乎这段程序,或者说功能就没有办法实现了。

          为了实现其功能,我们只好让Triangle继承两个完全没有联系的类,如此一来,我们所期望的软件概念中的联系被Triangle实现,而两个基类则最大程度的反映了现实事物间的关系。如此,两个基类都做了自己该做的事情,而且是一件事情。但是新的问题出现了,似乎Triangle做了两件事情,一件是Draw(),一件是把自己保存到XML文件中和从XML文件中获取自己。

          那么这又该如何应对呢?以笔者之愚见,Draw()这个方法根本不是Shape及其子类该做的事情,如果是我设计这段代码,我更倾向于将这三个方法放到一个抽象类(Operate)里,这个类专门负责对图形的操作,这样,Shape类及其子类最大程度上反应了现实世界中的事物,而我所说的Operate虽然在现实世界中找不到一个与之对应的具体实物,但它可以找到一个与之对应的抽象概念------操作图形。

          对于这个问题,我的思考还很混乱,也希望博友们能给些意见,更欢迎大家批评指正。

           

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷python

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值