zoukankan      html  css  js  c++  java
  • OOD沉思录 --- 类和对象的关系 --- 包含关系2

    4.6 尽量让类中定义的每个方法尽可能多地使用包含的对象(即数据成员)

    这其实就是高内聚的翻版强调。如果每个类的情况并非如此,那很可能是这一个类表示了两个或更多的概念,记住一个类只应该表示一个概念。    

    最明显的情况就是类的一半方法使用了一半的数据成员,而另一半方法使用了另一半的数据成员,那么这个类就应该一分为二。    

    我们假设一个澡堂,有VIP客户和普通客户,各自有不同的服务(普通客户享受中专生服务,VIP客户享受大学生服务),则定义如下:

    1. class 澡堂  
    2. {  
    3.      stack<中专生> 普通服务员;  
    4.      stack<大学生> VIP服务员;  
    5.        
    6.      普通接待()  
    7.      {  
    8.           普通服务员.Pop().侍候();                 
    9.      }  
    10.      普通结帐()  
    11.      {  
    12.           普通服务员.Pop().结帐();  
    13.      }  
    14.   
    15.      Vip接待()  
    16.      {  
    17.           VIP服务员.Pop().侍候();  
    18.      }  
    19.      VIP结帐()  
    20.      {  
    21.           VIP服务员.Pop().结帐();  
    22.      }  
    23. }  
    这是一个我经常看到的类似结构,这种结构不可避免地会在使用者的代码里进行很多条件判断,来确定到底调用那个版本的方法,而这种判断最好避免。     
    原因在于这一个类包含了两个概念,一个是针对普通客户,一个是针对VIP客户,违反了本条原则,我们应当将其分开,这里可以考虑再次抽象
    1. class 澡堂  
    2. {          
    3.     abstract 接待();  
    4.     abstract 结帐();  
    5. }  
    6. class 普通澡堂:澡堂  
    7. {  
    8.      stack<中专生> 服务员;           
    9.      接待()  
    10.      {  
    11.           服务员.Pop().侍候();                 
    12.      }  
    13.      结帐()  
    14.      {  
    15.           服务员.Pop().结帐();  
    16.      }  
    17. }  
    18. class VIP澡堂:澡堂  
    19. {  
    20.      stack<大学生> 服务员;  
    21.   
    22.      Vip接待()  
    23.      {  
    24.           服务员.Pop().侍候();  
    25.      }  
    26.      VIP结帐()  
    27.      {  
    28.           服务员.Pop().结帐();  
    29.      }  
    30. }  

        这样这个类的使用者可以使用如下方法:

    1. 澡堂 tmp=null;  
    2. if(顾客 is 普通客户)  
    3.      tmp=new 普通澡堂();         
    4. if(顾客 is VIP客户)  
    5.      tmp=new VIP澡堂();  
    6. tmp.接待();  
    7. //......  
    8. tmp.结帐();  

        眼神好的可能马上就会提出,这里也进行了判断,但是这里的判断我们可以通过两种手段来处理    

    一,字典        

    在外部保存一个字典:Dictionary<顾客类型,澡堂> dic;         那么上面的代码就成为下面这样:

    1. 澡堂 tmp=dic[顾客类型];  
    2. tmp.接待();  
    3. //......  
    4. tmp.结帐();  

    二,简单工厂        

    实现一个简单工厂,澡堂Factory,则使用代码如下:

    1. 澡堂 tmp=澡堂Factory.Create(顾客类型);  
    2. tmp.接待();  
    3. //......  
    4. tmp.结帐();  

         这两种方式都可以在程序配置的时候进行调整,将类型的依赖延迟到配置细节中(而这正是类型注入的要旨,别被那些专有的很玄的框架名次忽悠,其实就是这么简单)。

  • 相关阅读:
    LeetCode 227. Basic Calculator II
    LeetCode 224. Basic Calculator
    LeetCode 103. Binary Tree Zigzag Level Order Traversal
    LeetCode 102. Binary Tree Level Order Traversal
    LeetCode 106. Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode 105. Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode 169. Majority Element
    LeetCode 145. Binary Tree Postorder Traversal
    LeetCode 94. Binary Tree Inorder Traversal
    LeetCode 144. Binary Tree Preorder Traversal
  • 原文地址:https://www.cnblogs.com/stst/p/4909640.html
Copyright © 2011-2022 走看看