OOD沉思录 --- 类和对象的关系 --- 包含关系3
4.7 类包含的对象数目不应当超过开发者短期记忆数量,这个数目通常应该是6左右
4.8 让系统在窄而深的包含体系中垂直分布
假设有如下两份菜单:
正餐 --->甜瓜
--->牛排
--->土豆
--->豌豆
--->玉米
--->馅饼
或者
正餐 --->甜瓜
--->牛排套餐
--->牛排
--->配菜--->豌豆
--->土豆
--->玉米
--->馅饼
对使用者来说,哪种更科学呢?
回答1或者回答2都是错的,面向对象的使用者从不关心菜单的具体实现,只关心其公共接口(价格,份量,味道等)
那么对于实现者来说,哪种更科学呢?
面向过程的程序员可能会选择1,因为他不希望计算正餐价格的时候出现: 价格= ...+正餐.牛排套餐.配菜.豌豆.Get价格()+正餐.牛排套餐.配菜.土豆.Get价格()+... 而更喜欢:价格=甜瓜.Get价格()+牛排.Get价格()+...+馅饼.Get价格().
但是在面向对象的世界里,并不存在前者担忧的状况,出现他们所担忧的状况的原因只有一个原因,就是违反了经验原则
其实这里,模式大师已经作出了最完美的解决方案,那就是组合模式.
考虑我们现在讨论的问题都是关于的菜单上的菜肴,那么我们可以定义一个抽象的菜肴类,其中只关心价格属性
- class 菜肴
- {
- abstract double Get价格();
- virtual void Add(菜肴 para){}
- }
那么我们可以按照套餐的定义进行各个菜肴的定义
- class 甜瓜:菜肴
- {
- int count;//甜瓜是以个为单位计价
- readonly int 单价=10;//假设单价为常数
- double Get价格(){return 单价*count;}
- }
- class 牛排:菜肴
- {
- double weight;//牛排是以重量为单位计价
- readonly int 单价=20;//假设单价为常数
- double Get价格(){ return 单价*weight; }
- }
- class 豌豆:菜肴
- {
- double Get价格(){ return 5; }//豌豆包吃饱,5块钱
- }
- class 土豆:菜肴
- {
- double Get价格(){ return 5; }//土豆包吃饱,5块钱
- }
- class 玉米:菜肴
- {
- double Get价格(){ return 5; }//玉米包吃饱,5块钱
- }
- class 馅饼:菜肴
- {
- double piece;//馅饼按块计价
- readonly int 单价=5;//假设单价为常数
- double Get价格(){ return 单价*piece; }
- }
那么配菜,牛排套餐,正餐的概念呢?他们是由多份菜肴组合起来的复合体,专门针对计算价格来说,并不需要区分他们的区别,所以不需要针对每项建立一个类模型,我们只 定义一个组合菜肴类就可以满足需求:
- class 组合菜肴:菜肴
- {
- list<菜肴> lst;
- double Get价格()
- {
- double sum=0;
- foreach(菜肴 enu in lst)
- sum+=enu.Get价格();
- return sum;
- }
- override void Add(菜肴 para)
- {
- lst.Add(para);
- }
- }
那么我们可以通过外部配置的方式建立 配菜,牛排套餐,正餐 的概念,即
- 组合菜肴 正餐=new 组合菜肴();
- 正餐.Add(new 甜瓜);
- 正餐.Add(new 馅饼);
- 组合菜肴 牛排套餐=new 组合菜肴();
- 牛排套餐.Add(new 牛排);
- 组合菜肴 配菜=new 组合菜肴();
- 配菜.Add(new 豌豆);
- 配菜.Add(new 土豆);
- 配菜.Add(new 玉米);
- 牛排套餐.Add(配菜);
- 正餐.Add(牛排套餐);
顾客使用完正餐后结帐的调用很简单:
- 正餐.Get价格();
这里从头到尾都没有出现 正餐.牛排套餐.配菜.豌豆.Get价格() 形式的调用,而且将菜肴的组合需求放到了最后配置时,我们可以使用更灵活的方式配置各种套餐。
在这里,生成组合的代码就非常灵活了,工厂模式,生成器模式等等都可以根据你的需要进行套用了
OOD沉思录 --- 类和对象的关系 --- 包含关系3的更多相关文章
- OOD沉思录 --- 类和对象的关系 --- 包含关系1
4.5 如果类包含另一个类的对象,那么包含类应当向被包含的对象发送消息(调用方法). 也就是说,所有的包含关系都应当是使用关系. 如果不是这样,那么包含的类有什么用处呢?当然,面向过程的开发人员会想 ...
- OOD沉思录 --- 类和对象的关系 --- 包含关系4
4.9 在实现语义约束时,最好根据类定义来实现.但是这经常会导致泛滥成灾的类,在这种情况下约束应当在类的行为中实现,通常在类的构造函数中实现,但不是必须如此. 还是以汽车为例,我们看汽车的定义,为了集 ...
- OOD沉思录 --- 类和对象的关系 --- 包含关系2
4.6 尽量让类中定义的每个方法尽可能多地使用包含的对象(即数据成员) 这其实就是高内聚的翻版强调.如果每个类的情况并非如此,那很可能是这一个类表示了两个或更多的概念,记住一个类只应该表示一个概念. ...
- OOD沉思录 --- 类和对象的关系 --- 使用关系
使用关系 对象A的方法MethodA使用了B的方法MethodB,则表示A对B存在使用关系 使用关系的最关键问题在于,A如何找到B,存在6种方案 方案一: A包含了B,B作为一个成员定义在A的类中,那 ...
- OOD沉思录 --- 类和对象的关系 --- 使用关系原则
4.1 尽量减少类的协作的数量,即减少使用者和被使用者的数量. 协作意味着一定程度的耦合,但是完全没有协作的类也是没有意义的,最多只能作为一个库使用. 通过抽象,依赖接口,可以最大程度减少依赖的实现类 ...
- php课程 11-37 类和对象的关系是什么
php课程 11-37 类和对象的关系是什么 一.总结 一句话总结:类生成对象,对象是类的实例化,一定是先有类,后有对象,一定是先有标准,再有个体. 1.oop的三大优势是什么? 重用性,灵活性.扩展 ...
- OC学习--类和对象的关系
1. 如何创建对象 面向对象解决问题的时候必须有对象, 那应该如何创建对象? 以建造汽车为例子来解释: >建造汽车需要造车图纸, 图纸上 清楚的描述出 汽车具备的属性和功能(行为) >属性 ...
- Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员、局部),匿名对象的调用,构造代码块(5)
Java面向对象(概述,构造函数,类与对象的关系,this关键字,成员.局部),匿名对象的帝爱用,构造代码块(5)
- 2.java面向对象类与类/类与对象之间关系详解
继承.实现.依赖.关联.聚合.组合的联系与区别 下面的内容很基础,同时也很简单,但是也很重要. 继承 指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功 ...
随机推荐
- Django--models基础
需求 了解models字段和参数 速查 models.py 1 2 3 class UserInfo(models.Model): ctime = models.DateTimeField( ...
- JAVA魔法堂:读取.properties配置文件
一.前言 Java工程中想log4j.数据库连接等配置信息一般都写在.properties文件中,那么如何读取这些配置信息呢?下面把相关方法记录下来供以后查阅. 二..properties文件 配置文 ...
- CSS魔法堂:Position定位详解
一.Position各属性值详解 1. static :默认值,元素将按照正常文档流规则排列. 2. relative :相对定位,元素仍然处于正常文档流当中,但可以通过left.top. ...
- mysql如何更改数据库名(一键实现mysql改数据库名)
由于某种原因,有时我们有可能需要数据库的名称,但是不像官方有rename可以去更改表名,并没有一个命令可以去更新数据库的名字. 思路:借助rename这个命令 基本操作:rename olddb.ta ...
- MySQL扩展功能 - 重复插入
replace into为什么不好?先删除,后插曲,删除时会全表扫描吗? 参考来自MySQL官方网络的文档: http://dev.mysql.com/doc/refman/5.0/en/replac ...
- UnityShader快速上手指南(二)
简介 前一篇介绍了如果编写最基本的shader,接下来本文将会简单的深入一下,我们先来看下效果吧 呃,gif效果不好,实际效果是很平滑的动态过渡 实现思路 1.首先我们要实现一个彩色方块 2.让色彩动 ...
- css:条件注释判断浏览器
所有的IE可识别 Target ALL VERSIONS of IE <!--[if IE]> <link rel="stylesheet" type=" ...
- 用Perl编写Apache模块续二 - SVN动态鉴权实现SVNAuth 禅道版
代码地址:https://code.csdn.net/x3dcn/svnauth 以禅道项目管理系统的数据库结构为标准,实现了可用的svn authz验证功能. 以用户名.密码.项目的acl开发程度o ...
- 树的统计Count---树链剖分
NEFU专项训练十和十一——树链剖分 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t ...
- Spring核心概念之AOP
一.AOP 的概念 AOP(Aspect Oriented Programming)的缩写,面向切面编程,主要作用就是对代码进行增强处理. 理解面向切面编程的含义:就是在不改变原有程序的基础上为代码增 ...