小话设计模式(九)组合模式
组合(Composite)模式将对象组合成树形结构以表示“部分-整体”的层次结构。这样使得用户对单个对象和组合对象的使用具有一致性。
组合模式,听名字你可能比较陌生,但是你很可能是这种模式的用户,它的应用非常广泛,例如IOS里的UIView、Cocos2d-x里的Node以及Unity3d里的Transform都是典型的组合模式。
本文简单举个例子,假设我们要开发一款机甲类的游戏,机甲由身体、手臂、腿等组件组成,这些部件还可以搭载火箭助推器和激光加农炮等组件,那么我们就可以考虑使用组合模式来设计。
首先定义一个机器组件的抽象类:
public abstract class RobotComponent
{protected RobotComponent _parent = null;public virtual RobotComponent parent{ get { return _parent;} set{ if (_parent == value) {return;}if (_parent != null) {_parent.RemoveComponentFromList (this);}_parent = value;if (_parent != null) {_parent.AddComponentToList (this);}}}public virtual void RemoveFromParent (){parent = null;}protected List<RobotComponent> _children = new List<RobotComponent> ();protected virtual void AddComponentToList(RobotComponent component){if (!CanAddComponent (component)) {return;}if (!_children.Contains (component)) {_children.Add (component);}}public virtual RobotComponent AddComponent(RobotComponent component){component.parent = this;return component;}public RobotComponent AddComponent<T> () where T : RobotComponent, new(){RobotComponent component = new T ();return AddComponent (component);}protected virtual void RemoveComponentFromList (RobotComponent component){if (!_children.Contains (component)) {return;}_children.Remove (component);component._parent = null;}protected virtual bool CanAddComponent(RobotComponent component){return true;}
}
这个抽象类维护了一个RobotComponent类型的List,用来存放子组件,对外开放了AddComponent和RemoveFromParent方法以及Parent属性。
接着我们可能会考虑到某种类型的组件不能为它添加子组件,例如火箭助推器和激光加农炮,所以我们又定义了一个抽象类——LeafRobotComponent。
public abstract class LeafRobotComponent : RobotComponent
{ public override RobotComponent AddComponent(RobotComponent component){Console.WriteLine ("LeafRobotComponent cannot add component!");return null;}protected override void RemoveComponentFromList (RobotComponent component){Console.WriteLine ("LeafRobotComponent cannot add component! So removing component make no sense!");}
}
还有,机器人的身体应该不能被添加到其他组件上,所以需要再定义一个抽象类——RootRobotComponent。
public abstract class RootRobotComponent : RobotComponent
{ public override RobotComponent parent{ get { return null;} set{ Console.WriteLine ("RootRobotComponent cannot has a parent!");_parent = null;}}
}
这样我们就完成了一个包含根和叶的组合体系了。
然而还没有具体的功能,我们为RobotComponent添加一些属性,并修改CanAddComponent方法。
public abstract class RobotComponent
{protected RobotComponent _parent = null;public virtual RobotComponent parent{ get { return _parent;} set{ if (_parent == value) {return;}if (_parent != null) {_parent.RemoveComponentFromList (this);}_parent = value;if (_parent != null) {_parent.AddComponentToList (this);}}}public virtual void RemoveFromParent (){parent = null;}protected List<RobotComponent> _children = new List<RobotComponent> ();protected virtual void AddComponentToList(RobotComponent component){if (!CanAddComponent (component)) {return;}if (!_children.Contains (component)) {_children.Add (component);}}public virtual RobotComponent AddComponent(RobotComponent component){component.parent = this;return component;}public RobotComponent AddComponent<T> () where T : RobotComponent, new(){RobotComponent component = new T ();return AddComponent (component);}protected virtual void RemoveComponentFromList (RobotComponent component){if (!_children.Contains (component)) {return;}_children.Remove (component);component._parent = null;}protected virtual bool CanAddComponent(RobotComponent component){if (RemainingTech <= component.TechCost) {Console.WriteLine ("We do not have enough technology");return false;}return true;}protected int _attack = 0;public virtual int Attack{get {int ret = _attack;foreach (var comp in _children) {ret += comp.Attack;}return ret;}}protected int _speed = 0;public virtual int Speed{get {int ret = _speed;foreach (var comp in _children) {ret += comp.Speed;}return ret;}}protected int _techCost = 0;public virtual int TechCost{get {int ret = _techCost;foreach (var comp in _children) {ret += comp.TechCost;}return ret;}}protected int _maxTech = 0;public virtual int RemainingTech{get {int ret = _maxTech;foreach (var comp in _children) {ret -= comp.TechCost;if (ret < 0) {ret = 0;break;}}if (_parent != null && ret > _parent.RemainingTech) {ret = _parent.RemainingTech;}return ret;}}
}
然后我们定义继承自RootRobotComponent的RobotBody:
public class RobotBody:RootRobotComponent
{public RobotBody(){_maxTech = 100;}
}
继承自RobotComponent的RobotArm和RobotLeg:
public class RobotArm : RobotComponent
{public RobotArm(){_attack = 10;_techCost = 20;_maxTech = 10;}
}public class RobotLeg : RobotComponent
{public RobotLeg(){_attack = 5;_speed = 5;_techCost = 20;_maxTech = 10;}
}
以及继承自LeafRobotComponent的RocketBooster和LaserCannon:
public class RocketBooster : LeafRobotComponent
{public RocketBooster(){_techCost = 3;}public override int Speed{get {return 2;}}
}public class LaserCannon : LeafRobotComponent
{public LaserCannon(){_techCost = 3;}public override int Speed{get {return -1;}}public override int Attack{get {return 3;}}
}
然后我们就可以组装机甲了:
RobotComponent robot = new RobotBody ();RobotComponent arm1 = new RobotArm ();//robot.AddComponent<RobotArm> ();RobotComponent arm2 = robot.AddComponent<RobotArm> ();RobotComponent leg1 = new RobotLeg ();//robot.AddComponent<RobotLeg> ();RobotComponent leg2 = robot.AddComponent<RobotLeg> ();arm1.AddComponent<LaserCannon> ();arm2.AddComponent<LaserCannon> ();leg1.AddComponent<RocketBooster> ();leg2.AddComponent<RocketBooster> ();robot.AddComponent<RocketBooster> ();robot.AddComponent<RocketBooster> ();robot.AddComponent (arm1);robot.AddComponent (leg1);robot.AddComponent<LaserCannon> ();Console.WriteLine (robot.RemainingTech);Console.WriteLine (robot.Speed);Console.WriteLine (robot.Attack);
输出:
We do not have enough technology
2
16
36
组合模式的优点:
1、定义了组合对象的层次结构,可以不断的递归产生各种复杂的组件。
2、简化了用户的代码,用户可以一致地使用组合组件和单个组件。
3、易于增加新类型的组件,新组件添加后可以和原来的组件一起使用。
缺点:
很难限制组合中的组件:有时候你可能希望一个组合只能包含某些特定的组件,就只能在运行时进行检查。
小话设计模式(九)组合模式相关推荐
- 小话设计模式:Builder模式
尊重他人的劳动成果,转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/52764455, 本文出自:[gengqiquan的博客] 有一天 ...
- 小话设计模式(番外二)委托模式
委托(Delegate)模式定义了对象之间的一对一的关系,被委托方可以作为委托方的事件接收者或者数据源(Data Source),当它作为事件接受者的时候,可以认为它是一种特殊的观察者(参考小话设计模 ...
- 小话设计模式(十)外观模式
外观(Fascade)模式定义一个高级的接口,将子系统里的一组接口整合起来,提供了一个统一的外观. 在以下情况下可以考虑使用外观模式: (1)设计初期阶段,应该有意识的将不同层分离,层与层之间建立外观 ...
- C#软件设计——小话设计模式原则之:依赖倒置原则DIP
前言:很久之前就想动笔总结下关于软件设计的一些原则,或者说是设计模式的一些原则,奈何被各种bootstrap组件所吸引,一直抽不开身.群里面有朋友问博主是否改行做前端了,呵呵,其实博主是想做" ...
- 每天一个设计模式之组合模式
作者按:<每天一个设计模式>旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现.诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) ...
- Java设计模式之组合模式详解
文章目录 详解Java设计模式之组合模式 案例引入 组合模式 定义 模式类图结构 相关角色 典型代码 案例分析 类图设计 实例代码 结果分析 JavaJDK中的组合模式 透明组合模式 安全组合模式 组 ...
- Java设计模式之组合模式(UML类图分析+代码详解)
大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设 ...
- 1、【设计模式】组合模式
java设计模式之组合模式 [学习难度:★★★☆☆,使用频率:★★★★☆] 树形结构在软件中随处可见,例如操作系统中的目录结构.应用软件中的菜单.办公系统中的公司组织结构等等,如何运用面向对象的方式 ...
- C#软件设计——小话设计模式原则之:接口隔离原则ISP
前言:有朋友问我,设计模式原则这些东西在园子里都讨论烂了,一搜一大把的资料,还花这么大力气去整这个干嘛.博主不得不承认,园子里确实很多这方面的文章,并且不乏出色的博文.博主的想法是,既然要完善知识体系 ...
- 详解设计模式:组合模式
组合模式(Composite Pattern),又叫部分整体模式,是 GoF 的 23 种设计模式中的一种结构型设计模式. 组合模式 是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组 ...
最新文章
- GARFIELD@01-24-2005
- fusion 360安装程序的多个实例正在同时运行。_SpringMVC运行原理
- POJ 2976 01分数规划基础题目
- android cts 编译,使用 Android studio 分析运行 CTS 用例
- SSH连接服务器报错(WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED)的解决方案
- Mac iterm2 终端优化
- 哲学家就餐(避免死锁)(多进程版)
- java sleep和wait区别
- ubuntu14.04 安装 pyv8
- MySQL数据库 资源
- 计算机输入什么指令关机,电脑自动关机命令是什么【详细介绍】
- hi3519叠加OSD
- 很哇塞的网页特效之字符串切换
- Linux安装rar压缩软件
- 微信小程序——给用户发送通知
- 一起学WEB HTML5 第1讲
- php+病毒代码,蠕虫病毒VB代码
- mysql repair 所有表_MySQL磁盘满repair多个表问题的解决
- python获取星期几_如何在Python中获取日期的星期几?
- [论文笔记]Trajectory Data Driven V2V/V2I Mode Switching and Bandwidth Allocation for Vehicle Networks
热门文章
- 加入收藏夹,设为首页代码,强制设为主页代码
- 联通下调国际漫游数据流量资费
- MFC 获取所有USB设备 列举所有USB设备 列举所有USB HUB
- 2021年三季度中国服装家纺行业A股上市企业营收排行榜:海澜之家业绩突出,再度蝉联榜单TOP1(附热榜TOP61详单)
- 【项目实战】 ---- 简单整合SpringBoot + MyBatis + Themyleaf小项目
- BUUCTF:[SWPUCTF 2016]Web blogsys
- 骨骼动画——论文与代码精读《Phase-Functioned Neural Networks for Character Control》
- zz一篇很赞同的文章:2008年以后房价会降?想都不要想
- 人在回路的数据准备技术研究进展
- 2022年化工自动化控制仪表考试试题模拟考试平台操作