4.7 类包含的对象数目不应当超过开发者短期记忆数量,这个数目通常应该是6左右

4.8 让系统在窄而深的包含体系中垂直分布

假设有如下两份菜单:

正餐   --->甜瓜

    --->牛排

  --->土豆

--->豌豆

--->玉米

--->馅饼

或者

正餐  --->甜瓜

    --->牛排套餐

    --->牛排

    --->配菜--->豌豆

        --->土豆

        --->玉米

        --->馅饼

对使用者来说,哪种更科学呢?

回答1或者回答2都是错的,面向对象的使用者从不关心菜单的具体实现,只关心其公共接口(价格,份量,味道等)

那么对于实现者来说,哪种更科学呢?

面向过程的程序员可能会选择1,因为他不希望计算正餐价格的时候出现: 价格= ...+正餐.牛排套餐.配菜.豌豆.Get价格()+正餐.牛排套餐.配菜.土豆.Get价格()+...     而更喜欢:价格=甜瓜.Get价格()+牛排.Get价格()+...+馅饼.Get价格().

但是在面向对象的世界里,并不存在前者担忧的状况,出现他们所担忧的状况的原因只有一个原因,就是违反了经验原则

其实这里,模式大师已经作出了最完美的解决方案,那就是组合模式.

考虑我们现在讨论的问题都是关于的菜单上的菜肴,那么我们可以定义一个抽象的菜肴类,其中只关心价格属性

  1. class 菜肴
  2. {
  3. abstract double Get价格();
  4. virtual void Add(菜肴 para){}
  5. }

那么我们可以按照套餐的定义进行各个菜肴的定义

  1. class 甜瓜:菜肴
  2. {
  3. int count;//甜瓜是以个为单位计价
  4. readonly int 单价=10;//假设单价为常数
  5. double Get价格(){return 单价*count;}
  6. }
  7. class 牛排:菜肴
  8. {
  9. double weight;//牛排是以重量为单位计价
  10. readonly int 单价=20;//假设单价为常数
  11. double Get价格(){ return 单价*weight; }
  12. }
  13. class 豌豆:菜肴
  14. {
  15. double Get价格(){ return 5; }//豌豆包吃饱,5块钱
  16. }
  17. class 土豆:菜肴
  18. {
  19. double Get价格(){ return 5; }//土豆包吃饱,5块钱
  20. }
  21. class 玉米:菜肴
  22. {
  23. double Get价格(){ return 5; }//玉米包吃饱,5块钱
  24. }
  25. class 馅饼:菜肴
  26. {
  27. double piece;//馅饼按块计价
  28. readonly int 单价=5;//假设单价为常数
  29. double Get价格(){ return 单价*piece; }
  30. }

那么配菜,牛排套餐,正餐的概念呢?他们是由多份菜肴组合起来的复合体,专门针对计算价格来说,并不需要区分他们的区别,所以不需要针对每项建立一个类模型,我们只 定义一个组合菜肴类就可以满足需求:

  1. class 组合菜肴:菜肴
  2. {
  3. list<菜肴> lst;
  4. double Get价格()
  5. {
  6. double sum=0;
  7. foreach(菜肴 enu in lst)
  8. sum+=enu.Get价格();
  9. return sum;
  10. }
  11. override void Add(菜肴 para)
  12. {
  13. lst.Add(para);
  14. }
  15. }

那么我们可以通过外部配置的方式建立 配菜,牛排套餐,正餐 的概念,即

  1. 组合菜肴 正餐=new 组合菜肴();
  2. 正餐.Add(new 甜瓜);
  3. 正餐.Add(new 馅饼);
  4. 组合菜肴 牛排套餐=new 组合菜肴();
  5. 牛排套餐.Add(new 牛排);
  6. 组合菜肴 配菜=new 组合菜肴();
  7. 配菜.Add(new 豌豆);
  8. 配菜.Add(new 土豆);
  9. 配菜.Add(new 玉米);
  10. 牛排套餐.Add(配菜);
  11. 正餐.Add(牛排套餐);

顾客使用完正餐后结帐的调用很简单:

  1. 正餐.Get价格();

这里从头到尾都没有出现 正餐.牛排套餐.配菜.豌豆.Get价格() 形式的调用,而且将菜肴的组合需求放到了最后配置时,我们可以使用更灵活的方式配置各种套餐。

在这里,生成组合的代码就非常灵活了,工厂模式,生成器模式等等都可以根据你的需要进行套用了

OOD沉思录 --- 类和对象的关系 --- 包含关系3的更多相关文章

  1. OOD沉思录 --- 类和对象的关系 --- 包含关系1

    4.5 如果类包含另一个类的对象,那么包含类应当向被包含的对象发送消息(调用方法).  也就是说,所有的包含关系都应当是使用关系. 如果不是这样,那么包含的类有什么用处呢?当然,面向过程的开发人员会想 ...

  2. OOD沉思录 --- 类和对象的关系 --- 包含关系4

    4.9 在实现语义约束时,最好根据类定义来实现.但是这经常会导致泛滥成灾的类,在这种情况下约束应当在类的行为中实现,通常在类的构造函数中实现,但不是必须如此. 还是以汽车为例,我们看汽车的定义,为了集 ...

  3. OOD沉思录 --- 类和对象的关系 --- 包含关系2

    4.6 尽量让类中定义的每个方法尽可能多地使用包含的对象(即数据成员) 这其实就是高内聚的翻版强调.如果每个类的情况并非如此,那很可能是这一个类表示了两个或更多的概念,记住一个类只应该表示一个概念. ...

  4. OOD沉思录 --- 类和对象的关系 --- 使用关系

    使用关系 对象A的方法MethodA使用了B的方法MethodB,则表示A对B存在使用关系 使用关系的最关键问题在于,A如何找到B,存在6种方案 方案一: A包含了B,B作为一个成员定义在A的类中,那 ...

  5. OOD沉思录 --- 类和对象的关系 --- 使用关系原则

    4.1 尽量减少类的协作的数量,即减少使用者和被使用者的数量. 协作意味着一定程度的耦合,但是完全没有协作的类也是没有意义的,最多只能作为一个库使用. 通过抽象,依赖接口,可以最大程度减少依赖的实现类 ...

  6. php课程 11-37 类和对象的关系是什么

    php课程 11-37 类和对象的关系是什么 一.总结 一句话总结:类生成对象,对象是类的实例化,一定是先有类,后有对象,一定是先有标准,再有个体. 1.oop的三大优势是什么? 重用性,灵活性.扩展 ...

  7. OC学习--类和对象的关系

    1. 如何创建对象 面向对象解决问题的时候必须有对象, 那应该如何创建对象? 以建造汽车为例子来解释: >建造汽车需要造车图纸, 图纸上 清楚的描述出 汽车具备的属性和功能(行为) >属性 ...

  8. Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员、局部),匿名对象的调用,构造代码块(5)

    Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员.局部),匿名对象的帝爱用,构造代码块(5)

  9. 2.java面向对象类与类/类与对象之间关系详解

    继承.实现.依赖.关联.聚合.组合的联系与区别 下面的内容很基础,同时也很简单,但是也很重要. 继承 指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功 ...

随机推荐

  1. Android 学习笔记之AndBase框架学习(二) 使用封装好的进度框,Toast框,弹出框,确认框...

    PS:渐渐明白,在实验室呆三年都不如在企业呆一年... 学习内容: 1.使用AbActivity内部封装的方法实现进度框,Toast框,弹出框,确认框...   AndBase中AbActivity封 ...

  2. JAVA生成随机数种子的方法

    Java里面有一个随机函数——Random,刚开始只是知道这个函数具有随机取值的作用,于是上网搜索了资料一番,做了一下一些关于Random函数的总结:   Java中存在着两种Random函数: 一. ...

  3. .NET框架面向对象分层的个人想理

    简单.层次清晰不要过度优化,接口这玩意儿就是个双刃剑,玩好了解藕,玩不好自找麻烦,好的代码永远都是傻瓜都能看懂的. 总结成以下几条: 公用层 代码公用并且与第三方DLL和业务逻辑无关的 独立出来 逻辑 ...

  4. Velocity魔法堂系列一:入门示例

    一.前言 Velocity作为历史悠久的模板引擎不单单可以替代JSP作为Java Web的服务端网页模板引擎,而且可以作为普通文本的模板引擎来增强服务端程序文本处理能力.而且Velocity被移植到不 ...

  5. 用Qt写软件系列二:QCookieViewer(浏览器Cookie查看器)

    预备 继上篇<浏览器缓存查看器QCacheViewer>之后,本篇开始QCookieViewer的编写.Cookie技术作为网站收集用户隐私信息.分析用户偏好的一种手段,广泛应用于各大网站 ...

  6. C#中CookieContainer获取里面cookie值异常:InvokeMember("m_domainTable") FieldAccessException

    1.可能是主机提供商的 安全问题. Their hosts works in medium trustsecurity, and ASProxy needs a full trust security ...

  7. JS实现注销功能

    JS实现注销功能,代码如下: <script> window.history.forward(1); </script> 这个代码的用法就是: 比如,我们此时有两个页面:Log ...

  8. BI之SSAS完整实战教程3 -- 创建第一个多维数据集

    上一篇我们已经完成了数据源的准备工作,现在我们就开始动手,创建第一个多维数据集(Cube). 文章提纲 使用多维数据集向导创建多维数据集 总结Cube设计器简介 维度细化 总结 一.使用向导创建多维数 ...

  9. n个人作m幅画

    题目网址: http://codeforces.com/problemset/problem/416/B A well-known art union called "Kalevich is ...

  10. pace.js和NProgress.js两个加载进度插件的一点小总结

    这两个插件都是关于加载进度动画的,应该说各有特点吧,最起码对我来说是各有优势的.今天一天就捣鼓了加载进度动画,也研究了大量的(也就这两个)加载进度动画,也算对加载进度动画有了一个初步的了解了吧. NP ...