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 ...
随机推荐
- js获取URL中的参数
js获取URL中的一些参数的意思 location对象 含有当前URL的信息. 属性 href 整个URL字符串. protocol 含有URL第一部分的字符串,如http: host 包含有URL中 ...
- apache的AB测试
A/B测试A/B测试是一种新兴的网页优化方法,可以用于增加转化率注册率等网页指标..A/B测试的目的在于通过科学的实验设计.采样样本代表性.流量分割与小流量测试等方式来获得具有代表性的实验结论,并确信 ...
- ListAdapter列表适配器
ListAdapter列表适配器其实是继承了BaseAdapter 示例图: MainActivity package com.shaoxin.mylistadapter; import androi ...
- javaweb学习笔记之servlet01
一.Servlet概述 A servlet is a small Java program that runs within a Web server. Servlets receive and re ...
- jQuery 遍历函数
转载http://www.cnblogs.com/tylerdonet/archive/2013/04/05/3000618.html jQuery 遍历函数包括了用于筛选.查找和串联元素的方法. 函 ...
- [转]关于SVN的操作批处理示例
为了一句话:不要动手做机器能够做的事情. 天天工作用svn,更新啥的打开目录啥的动作天天在重复.每次写些命令也蛮无聊的,不说了,看下面: @echo off rem 显示部分 @echo 注 意 事 ...
- Xcode8中处理打印日志的配置
Xcode8中处理打印日志的配置
- js中的navigator对象
Navigator 对象包含有关浏览器的信息.所有浏览器都支持该对象 在控制台中输出相关信息的代码 <script> console.log(navigator); </script ...
- homework-02
关于输入 先来说说关于输入的事情.其实我最一开始并没有发现输入数字之间是用逗号隔开的,所以我是当做空格隔开来写的,后来发现以后匆忙改正,利用strtok与atoi函数从字符串中提取出用逗号隔开的数字. ...
- 最小生成树 prime poj1258
题意:给你一个矩阵M[i][j]表示i到j的距离 求最小生成树 思路:裸最小生成树 prime就可以了 最小生成树专题 AC代码: #include "iostream" #inc ...