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 ...
随机推荐
- hash表及Java中的HashMap与HashSet
链接: http://alex09.iteye.com/blog/539545/ 当程序试图将一个 key-value 对放入 HashMap 中时,程序首先根据该 key 的 hashCode() ...
- FMDB 排它锁
-------------------------------------基本操作------------------------------------- #import "ViewCon ...
- git 查看某文件的修改历史
前提 先进入此文件所在的目录下 1. git log filename可以看到fileName相关的commit记录2. git log -p filename可以显示每次提交的diff3. 只看某次 ...
- mac-改造你的terminal
今天在知乎上看到了一篇关于<程序员如何优雅使用Mac>,里面介绍了不少Mac的高端使用技巧,其中关于terminal的部分更是深深的吸引了我,于是我也开始了我的terminal改造计划. ...
- [转]oracle分析函数Rank, Dense_rank, row_number
oracle分析函数Rank, Dense_rank, row_number 分析函数2(Rank, Dense_rank, row_number) 目录 ==================== ...
- java基础-泛型3
浏览以下内容前,请点击并阅读 声明 8 类型擦除 为实现泛型,java编译器进行如下操作进行类型擦除: 如果类型参数有限制则替换为限制的类型,如果没有则替换为Object类,变成普通的类,接口和方法. ...
- 在HTML中使用JavaScript元素
script属性<script async = async charset="utf-8" defer="defer" src="index.h ...
- bzoj1503郁闷的出(cheng)纳(xu)员
好痛苦,,,WA了不知道多少遍 错的服了,,, 如果某员工的初始工资低于工资下界,他将立刻离开公司 我也不知道是我语文有问题还是题目有毒,反正这个东西好像不应该算在离开公司的总人数的答案里... 让我 ...
- python实现简单爬虫功能
在我们日常上网浏览网页的时候,经常会看到一些好看的图片,我们就希望把这些图片保存下载,或者用户用来做桌面壁纸,或者用来做设计的素材. 我们最常规的做法就是通过鼠标右键,选择另存为.但有些图片鼠标右键的 ...
- Linux Shell 脚本调试
方法如下所示:(1) 使用选项–x,启用shell脚本的跟踪调试功能: $ bash -x script.sh 运行带有-x标志的脚本可以打印出所执行的每一行命令以及当前状态.注意,你也可以使用sh ...