C#设计模式之组合
IronMan之组合
在上个篇幅中讲到怎么把“武器”装饰到“部件”上,这个篇幅呢,还是要讲到“武器”,不过呢是关于“武器”使用的。
本篇介绍"武器"的合理使用方式,不说废话,直接来看起初使用遇到的问题:
一起来看一下“武器”的定义:
public abstract class WeaponUpgradeLevel1
{
protected List<WeaponUpgradeLevel1> weaponUpgrades=new List<WeaponUpgradeLevel1>(); public List<WeaponUpgradeLevel1> WeaponUpgrades
{
get
{
return weaponUpgrades;
} }
/// <summary>
/// 判断是“部分”对象 还是 “整体”对象
/// </summary>
public bool IsSingle
{
get
{
if (weaponUpgrades.Count > )
{
return false;
}
else
{
return true;
}
}
}
/// <summary>
/// 攻击
/// </summary>
public abstract void Attack();
/// <summary>
/// 添加 “部分”对象或者是“整体”对象 到“整体”对象
/// </summary>
/// <param name="weaponupgrade"></param>
/// <returns></returns>
public virtual bool Add(WeaponUpgradeLevel1 weaponupgrade)
{
if (weaponupgrade != null)
{
WeaponUpgrades.Add(weaponupgrade);
return true;
}
else { return false; } }
/// <summary>
/// 从“整体”对象中移除 “部分”对象或者是“整体”对象
/// </summary>
/// <param name="weaponupgrade"></param>
/// <returns></returns>
public virtual bool Remove(WeaponUpgradeLevel1 weaponupgrade)
{
if (weaponupgrade != null)
{
if (WeaponUpgrades.Contains(weaponupgrade))
{
WeaponUpgrades.Remove(weaponupgrade);
return true;
}
else
{
return false;
}
}
else { return false; }
}
}
public class Rocket : WeaponUpgradeLevel1
{
private string _name = "火箭炮"; public override void Attack()
{
Console.WriteLine("使用" + _name + "进行攻击");
}
}
public class RocketLevel1 : WeaponUpgradeLevel1
{
private string _name = "火箭炮(EX.2X2)";//由四个火箭炮组成 public override void Attack()
{
Console.WriteLine("使用"+_name+"进行攻击");
}
}
上面定义了三种类型,WeaponUpgradeLevel1是“武器”的抽象,并且在其中定义了一些属性和方法,
用于表示实现了此“武器”抽象的类型是否是核心武器(部分)还是核心武器的外壳(整体),
并且也在后面实现了“武器”抽象,分别是Rocket核心武器(部分)和RocketLevel1核心武器的外壳(整体),这样的结构定义好了过后,我们来看一下子,怎么使用它们:
WeaponUpgradeLevel1 weaRocket1 = new Rocket();
WeaponUpgradeLevel1 weaRocket2 = new Rocket();
WeaponUpgradeLevel1 weaRocket3 = new Rocket();
WeaponUpgradeLevel1 weaRocket4 = new Rocket(); WeaponUpgradeLevel1 weaRocketlevel1 = new RocketLevel1();
weaRocketlevel1.Add(weaRocket1);
weaRocketlevel1.Add(weaRocket2);
weaRocketlevel1.Add(weaRocket3);
weaRocketlevel1.Add(weaRocket4);
这时候 weaRocketlevel1示例是像图1这样的:
图1

图2

要是使用weaRocketlevel1,真正的目的不是使用它本身,而是使用它里面的小火箭炮(也就是weaRocket1……)。 如果想要使用里面的小火箭炮,并不是简简单单的遍历一下就可以了,从现在的情况来看,确实是很简单的遍历
,获取到每个火箭炮,并且使用它们, 但是如果这个"火箭炮(EX.2X2)"改成了"火箭炮(EX.8X8)"呢? 并且"火箭炮(EX.8X8)"是由 4个"火箭炮(EX.4X4)"组成,每个"火箭炮(EX.4X4)"是由4个"火箭炮(EX.2X2)"组成的。 在这样的情况下怎么办? 没错了,是使用递归来遍历,然后的情况就是如图3所示:
图3

这样来看,也确实没什么大问题,只是耦合度比较高。
使用设计模式可以在特定的情况下解耦,这里的情况比较适合Composite模式。
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合
对象的使用具有一致性。
[GOF 《设计模式》]
根据设计的中心思想,看一下修改后的结构:
public abstract class WeaponUpgradeLevel1
{
protected List<WeaponUpgradeLevel1> weaponUpgrades=new List<WeaponUpgradeLevel1>(); public List<WeaponUpgradeLevel1> WeaponUpgrades
{
get
{
return weaponUpgrades;
} }
/// <summary>
/// 判断是“部分”对象 还是 “整体”对象。
/// true为“部分”对象 反之相对
/// </summary>
public bool IsSingle
{
get
{
if (weaponUpgrades.Count > )
{
return false;
}
else
{
return true;
}
}
}
/// <summary>
/// 攻击
/// </summary>
public virtual void Attack()
{
ActionAttack(this);
}
private void ActionAttack(WeaponUpgradeLevel1 weaponupgrade)
{
if (weaponupgrade.IsSingle)
{
weaponupgrade.Attack();
}
else
{
foreach (WeaponUpgradeLevel1 weapon in weaponupgrade.WeaponUpgrades)
{
ActionAttack(weapon);
}
}
}
/// <summary>
/// 添加 “部分”对象或者是“整体”对象 到“整体”对象
/// </summary>
/// <param name="weaponupgrade"></param>
/// <returns></returns>
public virtual bool Add(WeaponUpgradeLevel1 weaponupgrade)
{
if (weaponupgrade != null)
{
WeaponUpgrades.Add(weaponupgrade);
return true;
}
else { return false; } }
/// <summary>
/// 从“整体”对象中移除 “部分”对象或者是“整体”对象
/// </summary>
/// <param name="weaponupgrade"></param>
/// <returns></returns>
public virtual bool Remove(WeaponUpgradeLevel1 weaponupgrade)
{
if (weaponupgrade != null)
{
if (WeaponUpgrades.Contains(weaponupgrade))
{
WeaponUpgrades.Remove(weaponupgrade);
return true;
}
else
{
return false;
}
}
else { return false; }
}
}
public class Rocket : WeaponUpgradeLevel1
{
private string _name = "火箭炮"; public override void Attack()
{
Console.WriteLine("使用" + _name + "进行攻击");
}
}
public class RocketLevel1 : WeaponUpgradeLevel1
{
private string _name = "火箭炮(EX.2X2)";//由四个火箭炮组成 public override void Attack()
{
base.Attack();
Console.WriteLine("使用"+_name+"进行攻击");
}
}
看一下现在的客户端怎么使用“火箭炮”:
WeaponUpgradeLevel1 weaRocket1 = new Rocket();
WeaponUpgradeLevel1 weaRocket2 = new Rocket();
WeaponUpgradeLevel1 weaRocket3 = new Rocket();
WeaponUpgradeLevel1 weaRocket4 = new Rocket();
WeaponUpgradeLevel1 weaRocketlevel1 = new RocketLevel1();
weaRocketlevel1.Add(weaRocket1);
weaRocketlevel1.Add(weaRocket2);
weaRocketlevel1.Add(weaRocket3);
weaRocketlevel1.Add(weaRocket4);
weaRocketlevel1.Attack();
所示结果如图4
图4

根据设计模式的思想修改代码的区别是在“武器”抽象中把对“核心武器”的使用做了统一的使用。意思就不做阐述了可以自己理解理解。
作者:金源
出处:http://www.cnblogs.com/jin-yuan/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面
C#设计模式之组合的更多相关文章
- C#设计模式(10)——组合模式(Composite Pattern)
一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...
- c++设计模式15 --组合模式
今天研究了一下设计模式15 组合模式 本人是菜鸟一枚,所以一开始完全不懂组合究竟是什么意思.先上图一张,树形结构图: 文档说,如果想做出这样的结构,通常考虑组合模式.那是为什么呢?现在让我们看一下组合 ...
- 乐在其中设计模式(C#) - 组合模式(Composite Pattern)
原文:乐在其中设计模式(C#) - 组合模式(Composite Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 组合模式(Composite Pattern) 作者:weba ...
- JavaScript设计模式之----组合模式
javascript设计模式之组合模式 介绍 组合模式是一种专门为创建Web上的动态用户界面而量身制定的模式.使用这种模式可以用一条命令在多个对象上激发复杂的或递归的行为.这可以简化粘合性代码,使其更 ...
- C#设计模式(10)——组合模式(Composite Pattern)(转)
一.引言 在软件开发过程中,我们经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理就是这样的一个例子,因为目录可以包括单独的文件,也可以包括文件夹,文件夹又是由文件组成的,由于简单对象 ...
- 设计模式:组合(Composite)模式
设计模式:组合(Composite)模式 一.前言 关于Composite模式,其实就是组合模式,又叫部分整体模式,这个模式在我们的生活中也经常使用,比如说如果读者有使用Java的GUI编写过程序 ...
- C#设计模式:组合模式(Composite Pattern)
一,C#设计模式:组合模式(Composite Pattern) using System; using System.Collections.Generic; using System.Linq; ...
- 【GOF23设计模式】组合模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_组合模式.树状结构.杀毒软件架构.JUnite底层架构.常见开发场景 package com.test.composite ...
- 设计模式:组合模式(Composite)
定 义:将对象组合树形结构以表示“部分-整体”的层次结构.组合模式使得用户对单个对象和组合对象使用具有一致性. 结构图: Component类: abstract class Component ...
随机推荐
- Android网络定位服务定制简述
Android 添加高德或百度网络定位服务 Android的网络定位服务以第三方的APK方式提供服务,由于在国内Android原生自带的com.google.android.gms服务几乎处于不可用状 ...
- ubuntu14 备份
备份命令 # tar cvpjf backup.tar.bz2 –exclude=/proc –exclude=/lost+found –exclude=/backup.tar.bz2 –exclud ...
- fragment+viepager 的简单暴力的切换方式
这里是自定义了一个方法来获取viewpager private static ViewPager viewPager; public static ViewPager getMyViewPager() ...
- CC countari & 分块+FFT
题意: 求一个序列中顺序的长度为3的等差数列. SOL: 对于这种计数问题都是用个数的卷积来进行统计.然而对于这个题有顺序的限制,不好直接统计,于是竟然可以分块?惊为天人... 考虑分块以后的序列: ...
- GDB调试汇编堆栈
GDB调试汇编堆栈 分析过程 C语言源代码 int g(int x) { return x+6; } int f(int x) { return g(x+1); } int main(void) { ...
- block 从B界面向A界面传值
最近在改公司外包项目的代码,发现了一种block传值的用法很有意思,记录一下 A.B两个页面 在B界面.h中定义 @property (nonatomic,strong) void(^block)(N ...
- 第一次IT技术面试经历
一.技术总监面试问题: 1.Hibernate的应用项目例举 2.jsp标签库例举 3.oracle的增删改查 4.关系型数据库的关联关系 5.数据库分页操作 二.技术总监面试问题: 1.for循环中 ...
- 客户端连接注册Ejabberd新用户
今天需要使用客户端注册新用户,结果发现注册失败,在管理后台添加新用户成功.编译安装ejabberd就没有管了,经过翻论坛的到解决方法 在ejabberd.yml中. access: trusted_n ...
- indows server 2008 多用户远程桌面连接设置(验证有效
然后,在运行框中输入 gpedit.msc 之后,点击确定或者直接按键盘上的回车键 计算机配置-->管理模板-->Windows组件---->远程桌面服务--->远程桌面会话 ...
- WEB前端工程师(实践)制作天气预报难度:简单
需要准备:jQuery Bootstrap 天气预报API(本文中使用API可能会失效请灵活运用) CSS样式可以你自己去写这里只提出jQuery 请求数据和解析JSON数据 { "resu ...