设计模式 ( 十八 ):State状态模式 -- 行为型

1.概述

在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理。最直接的解决方案是将这些所有可能发生的情况全都考虑到。然后使用if... ellse语句来做状态判断来进行不同情况的处理。但是对复杂状态的判断就显得“力不从心了”。随着增加新的状态或者修改一个状体(if else(或switch case)语句的增多或者修改)可能会引起很大的修改,而程序的可读性,扩展性也会变得很弱。维护也会很麻烦。那么我就考虑只修改自身状态的模式。

例子1:按钮来控制一个电梯的状态,一个电梯开们,关门,停,运行。每一种状态改变,都有可能要根据其他状态来更新处理。例如,开门状体,你不能在运行的时候开门,而是在电梯定下后才能开门。

例子2:我们给一部手机打电话,就可能出现这几种情况:用户开机,用户关机,用户欠费停机,用户消户等。 所以当我们拨打这个号码的时候:系统就要判断,该用户是否在开机且不忙状态,又或者是关机,欠费等状态。但不管是那种状态我们都应给出对应的处理操作。

2.问题

对象如何在每一种状态下表现出不同的行为?

3.解决方案

状态模式:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。

4.适用性

在下面的两种情况下均可使用State模式:
1) • 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2) • 代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

5.结构

6.模式的组成

环境类(Context):  定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
抽象状态类(State):  定义一个接口以封装与Context的一个特定状态相关的行为。
具体状态类(ConcreteState):  每一子类实现一个与Context的一个状态相关的行为。

7.效果

State模式有下面一些效果:
状态模式的优点:
1 ) 它将与特定状态相关的行为局部化,并且将不同状态的行为分割开来: State模式将所有与一个特定的状态相关的行为都放入一个对象中。因为所有与状态相关的代码都存在于某一个State子类中, 所以通过定义新的子类可以很容易的增加新的状态和转换。另一个方法是使用数据值定义内部状态并且让 Context操作来显式地检查这些数据。但这样将会使整个Context的实现中遍布看起来很相似的条件if else语句或switch case语句。增加一个新的状态可能需要改变若干个操作, 这就使得维护变得复杂了。State模式避免了这个问题, 但可能会引入另一个问题, 因为该模式将不同状态的行为分布在多个State子类中。这就增加了子类的数目,相对于单个类的实现来说不够紧凑。但是如果有许多状态时这样的分布实际上更好一些, 否则需要使用巨大的条件语句。正如很长的过程一样,巨大的条件语句是不受欢迎的。它们形成一大整块并且使得代码不够清晰,这又使得它们难以修改和扩展。 State模式提供了一个更好的方法来组织与特定状态相关的代码。决定状态转移的逻辑不在单块的 i f或s w i t c h语句中, 而是分布在State子类之间。将每一个状态转换和动作封装到一个类中,就把着眼点从执行状态提高到整个对象的状态。这将使代码结构化并使其意图更加清晰。

2) 它使得状态转换显式化: 当一个对象仅以内部数据值来定义当前状态时 , 其状态仅表现为对一些变量的赋值,这不够明确。为不同的状态引入独立的对象使得转换变得更加明确。而且, State对象可保证Context不会发生内部状态不一致的情况,因为从 Context的角度看,状态转换是原子的—只需重新绑定一个变量(即Context的State对象变量),而无需为多个变量赋值

3) State对象可被共享 如果State对象没有实例变量—即它们表示的状态完全以它们的类型来编码—那么各Context对象可以共享一个State对象。当状态以这种方式被共享时, 它们必然是没有内部状态, 只有行为的轻量级对象。

状态模式的缺点:
1) 状态模式的使用必然会增加系统类和对象的个数。
2) 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

8.实现

我们用电梯的例子来说明:

简单地实现代码:

  1. <?php
  2. abstract class ILift {
  3. //电梯的四个状态
  4. const OPENING_STATE = 1;  //门敞状态
  5. const CLOSING_STATE = 2;  //门闭状态
  6. const RUNNING_STATE = 3;  //运行状态
  7. const STOPPING_STATE = 4; //停止状态;
  8. //设置电梯的状态
  9. public abstract function setState($state);
  10. //首先电梯门开启动作
  11. public abstract function open();
  12. //电梯门有开启,那当然也就有关闭了
  13. public abstract function close();
  14. //电梯要能上能下,跑起来
  15. public abstract function run();
  16. //电梯还要能停下来,停不下来那就扯淡了
  17. public abstract function stop();
  18. }
  19. /**
  20. * 电梯的实现类
  21. */
  22. class Lift extends  ILift {
  23. private $state;
  24. public function setState($state) {
  25. $this->state = $state;
  26. }
  27. //电梯门关闭
  28. public function close() {
  29. //电梯在什么状态下才能关闭
  30. switch($this->state){
  31. case ILift::OPENING_STATE:  //如果是则可以关门,同时修改电梯状态
  32. $this->setState(ILift::CLOSING_STATE);
  33. break;
  34. case ILift::CLOSING_STATE:  //如果电梯就是关门状态,则什么都不做
  35. //do nothing;
  36. return ;
  37. break;
  38. case ILift::RUNNING_STATE: //如果是正在运行,门本来就是关闭的,也说明都不做
  39. //do nothing;
  40. return ;
  41. break;
  42. case ILift::STOPPING_STATE:  //如果是停止状态,本也是关闭的,什么也不做
  43. //do nothing;
  44. return ;
  45. break;
  46. }
  47. echo ‘Lift colse <br>‘;
  48. }
  49. //电梯门开启
  50. public function open() {
  51. //电梯在什么状态才能开启
  52. switch($this->state){
  53. case ILift::OPENING_STATE: //如果已经在门敞状态,则什么都不做
  54. //do nothing;
  55. return ;
  56. break;
  57. case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以开启
  58. $this->setState(ILift::OPENING_STATE);
  59. break;
  60. case ILift::RUNNING_STATE: //正在运行状态,则不能开门,什么都不做
  61. //do nothing;
  62. return ;
  63. break;
  64. case ILift::STOPPING_STATE: //停止状态,淡然要开门了
  65. $this->setState(ILift::OPENING_STATE);
  66. break;
  67. }
  68. echo ‘Lift open <br>‘;
  69. }
  70. ///电梯开始跑起来
  71. public function run() {
  72. switch($this->state){
  73. case ILift::OPENING_STATE: //如果已经在门敞状态,则不你能运行,什么都不做
  74. //do nothing;
  75. return ;
  76. break;
  77. case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以运行
  78. $this->setState(ILift::RUNNING_STATE);
  79. break;
  80. case ILift::RUNNING_STATE: //正在运行状态,则什么都不做
  81. //do nothing;
  82. return ;
  83. break;
  84. case ILift::STOPPING_STATE: //停止状态,可以运行
  85. $this->setState(ILift::RUNNING_STATE);
  86. }
  87. echo ‘Lift run <br>‘;
  88. }
  89. //电梯停止
  90. public function stop() {
  91. switch($this->state){
  92. case ILift::OPENING_STATE: //如果已经在门敞状态,那肯定要先停下来的,什么都不做
  93. //do nothing;
  94. return ;
  95. break;
  96. case ILift::CLOSING_STATE: //如是电梯时关闭状态,则当然可以停止了
  97. $this->setState(ILift::CLOSING_STATE);
  98. break;
  99. case ILift::RUNNING_STATE: //正在运行状态,有运行当然那也就有停止了
  100. $this->setState(ILift::CLOSING_STATE);
  101. break;
  102. case ILift::STOPPING_STATE: //停止状态,什么都不做
  103. //do nothing;
  104. return ;
  105. break;
  106. }
  107. echo ‘Lift stop <br>‘;
  108. }
  109. }
  110. $lift = new Lift();
  111. //电梯的初始条件应该是停止状态
  112. $lift->setState(ILift::STOPPING_STATE);
  113. //首先是电梯门开启,人进去
  114. $lift->open();
  115. //然后电梯门关闭
  116. $lift->close();
  117. //再然后,电梯跑起来,向上或者向下
  118. $lift->run();
  119. //最后到达目的地,电梯挺下来
  120. $lift->stop();

显然我们已经完成了我们的基本业务操作,但是,我们在程序中使用了大量的switch…case这样的判断(if…else也是一样),首先是程序的可阅读性很差,其次扩展非常不方便。一旦我们有新的状态加入的话,例如新加通电和断点状态。我们势必要在每个业务方法里边增加相应的case语句。也就是四个函数open,close,run,stop都需要修改相应case语句。

状态模式:把不同状态的操作分散到不同的状态对象里去完成。看看状态类的uml类图:

代码实现:

  1. <?php
  2. /**
  3. *
  4. * 定义一个电梯的接口
  5. */
  6. abstract class LiftState{
  7. //定义一个环境角色,也就是封装状态的变换引起的功能变化
  8. protected  $_context;
  9. public function setContext(Context $context){
  10. $this->_context = $context;
  11. }
  12. //首先电梯门开启动作
  13. public abstract function open();
  14. //电梯门有开启,那当然也就有关闭了
  15. public abstract function close();
  16. //电梯要能上能下,跑起来
  17. public abstract function run();
  18. //电梯还要能停下来,停不下来那就扯淡了
  19. public abstract function stop();
  20. }
  21. /**
  22. * 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
  23. */
  24. class Context {
  25. //定义出所有的电梯状态
  26. static  $openningState = null;
  27. static  $closeingState = null;
  28. static  $runningState  = null;
  29. static  $stoppingState = null;
  30. public function __construct() {
  31. self::$openningState = new OpenningState();
  32. self::$closeingState = new ClosingState();
  33. self::$runningState =  new RunningState();
  34. self::$stoppingState = new StoppingState();
  35. }
  36. //定一个当前电梯状态
  37. private  $_liftState;
  38. public function getLiftState() {
  39. return $this->_liftState;
  40. }
  41. public function setLiftState($liftState) {
  42. $this->_liftState = $liftState;
  43. //把当前的环境通知到各个实现类中
  44. $this->_liftState->setContext($this);
  45. }
  46. public function open(){
  47. $this->_liftState->open();
  48. }
  49. public function close(){
  50. $this->_liftState->close();
  51. }
  52. public function run(){
  53. $this->_liftState->run();
  54. }
  55. public function stop(){
  56. $this->_liftState->stop();
  57. }
  58. }
  59. /**
  60. * 在电梯门开启的状态下能做什么事情
  61. */
  62. class OpenningState extends LiftState {
  63. /**
  64. * 开启当然可以关闭了,我就想测试一下电梯门开关功能
  65. *
  66. */
  67. public function close() {
  68. //状态修改
  69. $this->_context->setLiftState(Context::$closeingState);
  70. //动作委托为CloseState来执行
  71. $this->_context->getLiftState()->close();
  72. }
  73. //打开电梯门
  74. public function open() {
  75. echo ‘lift open...‘, ‘<br/>‘;
  76. }
  77. //门开着电梯就想跑,这电梯,吓死你!
  78. public function run() {
  79. //do nothing;
  80. }
  81. //开门还不停止?
  82. public function stop() {
  83. //do nothing;
  84. }
  85. }
  86. /**
  87. * 电梯门关闭以后,电梯可以做哪些事情
  88. */
  89. class ClosingState extends LiftState {
  90. //电梯门关闭,这是关闭状态要实现的动作
  91. public function close() {
  92. echo ‘lift close...‘, ‘<br/>‘;
  93. }
  94. //电梯门关了再打开,逗你玩呢,那这个允许呀
  95. public function open() {
  96. $this->_context->setLiftState(Context::$openningState);  //置为门敞状态
  97. $this->_context->getLiftState()->open();
  98. }
  99. //电梯门关了就跑,这是再正常不过了
  100. public function run() {
  101. $this->_context->setLiftState(Context::$runningState); //设置为运行状态;
  102. $this->_context->getLiftState()->run();
  103. }
  104. //电梯门关着,我就不按楼层
  105. public function stop() {
  106. $this->_context->setLiftState(Context::$stoppingState);  //设置为停止状态;
  107. $this->_context->getLiftState()->stop();
  108. }
  109. }
  110. /**
  111. * 电梯在运行状态下能做哪些动作
  112. */
  113. class RunningState extends LiftState {
  114. //电梯门关闭?这是肯定了
  115. public function close() {
  116. //do nothing
  117. }
  118. //运行的时候开电梯门?你疯了!电梯不会给你开的
  119. public function open() {
  120. //do nothing
  121. }
  122. //这是在运行状态下要实现的方法
  123. public function run() {
  124. echo ‘lift run...‘, ‘<br/>‘;
  125. }
  126. //这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了
  127. public function stop() {
  128. $this->_context->setLiftState(Context::$stoppingState); //环境设置为停止状态;
  129. $this->_context->getLiftState()->stop();
  130. }
  131. }
  132. /**
  133. * 在停止状态下能做什么事情
  134. */
  135. class StoppingState extends LiftState {
  136. //停止状态关门?电梯门本来就是关着的!
  137. public function close() {
  138. //do nothing;
  139. }
  140. //停止状态,开门,那是要的!
  141. public function open() {
  142. $this->_context->setLiftState(Context::$openningState);
  143. $this->_context->getLiftState()->open();
  144. }
  145. //停止状态再跑起来,正常的很
  146. public function run() {
  147. $this->_context->setLiftState(Context::$runningState);
  148. $this->_context->getLiftState()->run();
  149. }
  150. //停止状态是怎么发生的呢?当然是停止方法执行了
  151. public function stop() {
  152. echo ‘lift stop...‘, ‘<br/>‘;
  153. }
  154. }
  155. /**
  156. * 模拟电梯的动作
  157. */
  158. class Client {
  159. public static function main() {
  160. $context = new Context();
  161. $context->setLiftState(new ClosingState());
  162. $context->open();
  163. $context->close();
  164. $context->run();
  165. $context->stop();
  166. }
  167. }
  168. Client::main();

9.与其他相关模式

1)职责链模式
职责链模式和状态模式都可以解决If分支语句过多,
从定义来看,状态模式是一个对象的内在状态发生改变(一个对象,相对比较稳定,处理完一个对象下一个对象的处理一般都已确定),
而职责链模式是多个对象之间的改变(多个对象之间的话,就会出现某个对象不存在的现在,就像我们举例的公司请假流程,经理可能不在公司情况),这也说明他们两个模式处理的情况不同。
这两个设计模式最大的区别就是状态模式是让各个状态对象自己知道其下一个处理的对象是谁。
而职责链模式中的各个对象并不指定其下一个处理的对象到底是谁,只有在客户端才设定。
用我们通俗的编程语言来说,就是
状态模式:
  相当于If else if else;
  设计路线:各个State类的内部实现(相当于If,else If内的条件)
  执行时通过State调用Context方法来执行。
职责链模式:
  相当于Swich case
  设计路线:客户设定,每个子类(case)的参数是下一个子类(case)。
  使用时,向链的第一个子类的执行方法传递参数就可以。
就像对设计模式的总结,有的人采用的是状态模式,从头到尾,提前一定定义好下一个处理的对象是谁,而我采用的是职责链模式,随时都有可能调整链的顺序。

2)策略模式:(http://www.cnblogs.com/Mainz/archive/2007/12/15/996081.html)(状态模式是策略模式的孪生兄弟)
        状态模式和策略模式的实现方法非常类似,都是利用多态把一些操作分配到一组相关的简单的类中,因此很多人认为这两种模式实际上是相同的。
然而在现实世界中,策略(如促销一种商品的策略)和状态(如同一个按钮来控制一个电梯的状态,又如手机界面中一个按钮来控制手机)是两种完全不同的思想。当我们对状态和策略进行建模时,这种差异会导致完全不同的问题。例如,对状态进行建模时,状态迁移是一个核心内容;然而,在选择策略时,迁移与此毫无关系。另外,策略模式允许一个客户选择或提供一种策略,而这种思想在状态模式中完全没有。
       一个策略是一个计划或方案,通过执行这个计划或方案,我们可以在给定的输入条件下达到一个特定的目标。策略是一组方案,他们可以相互替换;选择一个策略,获得策略的输出。策略模式用于随不同外部环境采取不同行为的场合。我们可以参考微软企业库底层Object Builder的创建对象的strategy实现方式。而状态模式不同,对一个状态特别重要的对象,通过状态机来建模一个对象的状态;状态模式处理的核心问题是状态的迁移,因为在对象存在很多状态情况下,对各个business flow,各个状态之间跳转和迁移过程都是及其复杂的。
       例如一个工作流,审批一个文件,存在新建、提交、已修改、HR部门审批中、老板审批中、HR审批失败、老板审批失败等状态,涉及多个角色交互,涉及很多事件,这种情况下用状态模式(状态机)来建模更加合适;把各个状态和相应的实现步骤封装成一组简单的继承自一个接口或抽象类的类,通过另外的一个Context来操作他们之间的自动状态变换,通过event来自动实现各个状态之间的跳转。在整个生命周期中存在一个状态的迁移曲线,这个迁移曲线对客户是透明的。我们可以参考微软最新的WWF 状态机工作流实现思想。
      在状态模式中,状态的变迁是由对象的内部条件决定,外界只需关心其接口,不必关心其状态对象的创建和转化;
而策略模式里,采取何种策略由外部条件(C)决定。
      他们应用场景(目的)却不一样,State模式重在强调对象内部状态的变化改变对象的行为,Strategy模式重在外部对策略的选择,策略的选择由外部条件决定,
也就是说算法的动态的切换。但由于它们的结构是如此的相似,我们可以认为“状态模式是完全封装且自修改的策略模式”。即状态模式是封装对象内部的状态的,而策略模式是封装算法族的

10.总结与分析

状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。

设计模式 ( 十八 ):State状态模式 -- 行为型

时间: 2024-09-29 19:43:10

设计模式 ( 十八 ):State状态模式 -- 行为型的相关文章

JAVA设计模式十二--State(状态模式)

状态模式(State Pattern)是设计模式的一种,属于行为模式. 定义(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化.意图:允许一个对象在其内部状态改变时改变它的行为适用场景: 1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为. 2.一个操作中含有庞大的多分支结

设计模式21:State 状态模式(行为型模式)

State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. 如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转换之间引入紧耦合? 意图(Intent) 允许一个对象在其内部状态改变时改变它的行为.从而使对象看起来似乎修改了其行为.——<设计模式>GoF 结构(Structure) 示例代码 public enum Document

设计模式(20)--State(状态模式)--行为型

作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式. 状态模式允许一个对象在其内部状态改变的时候改变其行为.这个对象看上去就像是改变了它的类一样. 2.模式特点: 状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以

设计模式(八)--状态模式

设计模式部分大部分借鉴左萧龙博客:https://www.cnblogs.com/zuoxiaolong/p/pattern22.html 这个人讲复杂的问题能深入浅出,对我本人影响很大.大家可以去他博客拜读他的文章. 我们先来看看状态模式的定义吧. 定义:(源于Design Pattern):当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类.    上述是百度百科中对状态模式的定义,定义很简单,只有一句话,请各位形象的去理解这句话,它说当状态改变时,这个对象的行为也会变,

设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也经常遇到类似的情况,实现某一个功能有多种算法或者策略,我们能够依据环境或者条件的不同选择不同的算法或者策略来完毕该功能.如查找.排序等,一种经常使用的方法是硬编码(Hard Coding)在一个类中,如须要提供多种查找算法,能够将这些算法写到一个类中,在该类中提供多个方法,每个方法相应一个详细的查找算法:当然也能够将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件推断语句来进行选择.

【转】设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法:当然也可以将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件判断语句来进行选择.这

工作那些事(二十八)项目管理模式:项目型、职能型、矩阵型

在一个项目中,项目经理有多大权利,可以动用哪些资源,取决于项目管理模式,项目管理模式由公司的CTO来决定.简而言之,项目管理有三种模式:项目型.职能型.矩阵型. 下面先看看这三种模式,对项目经理来说都是什么作用. 1项目型 将所有的能兵强将集结在一起,财务部.业务部.IT管理部等的精英们脱离原有的岗位.形成一个正式的部门,并由项目经理领导.这样的优势是项目经理的权利很强.资源充足,所有的项目经理都希望有这样的团队.但是就公司而言,单独团队对公司整体资源的浪费,是显而易见的:对被抽调的个人而言,脱

详解state状态模式及在C++设计模式编程中的使用实例

原文地址:http://www.jb51.net/article/80713.htm 这篇文章主要介绍了state状态模式及在C++设计模式编程中的使用实例,在设计模式中策略用来处理算法变化,而状态则是透明地处理状态变化,需要的朋友可以参考下 每个人.事物在不同的状态下会有不同表现(动作),而一个状态又会在不同的表现下转移到下一个不同的状态(State).最简单的一个生活中的例子就是:地铁入口处,如果你放入正确的地铁票,门就会打开让你通过.在出口处也是验票,如果正确你就可以 ok,否则就不让你通

设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)

设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据“单一职责原则”,我们应该尽量将对象细化,使其只负责或呈现单一的职责,即将行为分布到各个对象中. 对于一个模块或者系统,可能由很多对象构成,而且这些对象之间可能存在相互的引用,在最坏的情况下,每一个对象都知道其他所有的对象,这无疑复杂化了对象之间的联系.虽然将一个系统分割成许多对象通常可以增强可复用性,但是对象间相互连接的激增又会降低其可复用性,大量的相互连接使得一个对象似乎不太可能