就一个类而言,应该仅有一个引起它变化的原因。每个类实现一个功能。
单一职责原则可以看作是低耦合、高内聚在面向对象原则上的引申,将职责定义为引起变化的原因,以提高内聚性来减少引起变化的原因。职责过多,可能引起它变化的原因就越多,这将导致职责依赖,相互之间就产生影响,从而极大的损伤其内聚性和耦合度。单一职责,通常意味着单一的功能,因此不要为类实现过多的功能点,以保证实体只有一个引起它变化的原因。
现在要写一个俄罗斯方块的游戏,需要设计两个类一个是界面类,一个是游戏数据类应该考虑将程序至少分为两个类:一个是窗口类,用于处理界面交互。另一个是游戏数据类。当有一天要改变界面或是移植到其他平台上就不涉及游戏逻辑的改变。
//游戏逻辑 class DataCompute { public: DataCompute(); ~DataCompute(); void setShapen(); void setPlace(); private: int mPlace[4]; //位置 int mShape[4]; //形状 }; class GameUI { public: GameUI(); ~GameUI(); void showViewCcon(); //游戏方块显示 private: DataCompute *mDataCompute; //游戏逻辑 int mStartButton; //开始按钮 int mEndButton; //结束按钮 };
游戏数据类中主要有两大功能,一个是方块的形状,有“L”形,“十”形,“口”形,还有一个是方块的移动,变换操作。按照开闭原则需要实现两个类,形状类Shape和位置类Place。当添加一个形状时(如“一”形),不影响方块的移动等操作。
//方块形状类 class Shape { public: Shape(); ~Shape(); void setShape(); private: }; //方块位置类 class Place { public: Place(); ~Place(); void setPlace(); private: }; //游戏界面类 class GameUI { public: GameUI(); ~GameUI(); void showViewCcon(); //游戏方块显示 private: Shape *mShape; //形状 Place *mPlace; //位置 int mStartButton; //开始按钮 int mEndButton; //结束按钮 };
继续来看Shape形状类,它可以表示有“L”形,“十”形,“口”形,“一”形等方块,违背类职责单一原则,需要改成n个类。
//方块形状类 class Shape { public: Shape(); ~Shape(); virtual void setShape(); private: }; //"一"形 class Shape1 : public Shape { public: Shape1(); ~Shape1(); virtual void setShape(); private: }; //"十"形 class Shape2 : public Shape { public: Shape2(); ~Shape2(); virtual void setShape(); private: }; //"L"形 class Shape3 : public Shape { public: Shape3(); ~Shape3(); virtual void setShape(); private: }; //"其他"形 class Shape4: public Shape { public: Shape4(); ~Shape4(); virtual void setShape(); private: }; //方块位置类 class Place { public: Place(); ~Place(); void setPlace(); private: }; //游戏界面类 class GameUI { public: GameUI(); ~GameUI(); void showViewCcon(); //游戏方块显示 private: Shape *mShape; //形状 Place *mPlace; //位置 int mStartButton; //开始按钮 int mEndButton; //结束按钮 };
遵循单一职责原则改进代码时,发现各个类之间的耦合的不断降低。但类的个数从2个增加到类7+个,系统明显复杂了不少。而且还有些类的功能不符合职责单一原则,比如计算方块位置的类,它就包含两个功能,一个是方块在视图上的坐标(x,y),一个是方块当时的姿态(横的还是竖的等)。如果按这样无休止的分下去,类的个数增加太多类。系统反而会比较复杂难以维护。单一职责原则不应一味的追求单一职责,而是根据当前系统的大小,复杂度等实际情况,划分模块,设计类,达到系统的模块化,可维护特点。