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 ...
随机推荐
- CozyRSS开发记录8-解析一份RSS
CozyRSS开发记录8-解析一份RSS 1.使用Rss20FeedFormatter解析RSS 使用Rss20FeedFormatter配合XmlReader来解析RSS非常的简单,几行搞定: 来试 ...
- CURL 模拟http提交
1:CURL模拟get提交 private function httpGet($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_RETUR ...
- 使用logrotate分割Tomcat的catalina日志
切割catalian日志的方式有很多种,比如shell脚本的.cronolog或者通过配置log4j等等这些都可以实现.但今天我要介绍是使用logrotate来按日期生成日志. 原文是一个外国博主的文 ...
- css 简析folat
1.float?? 不知道大家是否还记得之前我们讲过页面是文档流,具体什么是文档流,我就不说了?于是我们页面布局如果用div的话,那么块状的元素是怎么排列的,什么叫块状自己去看? 如果我们呢用div布 ...
- Array方法
1.concat()方法 用法:用于连接两个或者多个数组. 对原数组有无影响:不会改变原有数组,会返回一个连接之后的数组. 2.join()方法 用法:以指定的分隔符把数组中每一项拆分成字符串. 对原 ...
- mssql查询列名中包含特定字段的列
CREATE TABLE itemdata_LANG ( itemno ) NOT NULL, itemname ), -- 产品名称 othername ), indications ), -- 适 ...
- elasticsearch一些常用的配置
配置了解 cluster #配置下集群的名称 cluster.name: my-application
- 站内全文检索服务来了,Xungle提供免费全文检索服务
免费站内全文检索服务来了,是的,你没听错.全文检索相信大家已经不太陌生,主流检索服务有sphinx.xunsearch等,但这些都受服务器限制,对于中小站长尤其是没有服务器实现就困难了,随着数据量的增 ...
- bzoj 2563: 阿狸和桃子的游戏
开始写了一些东西但是后来浏览器挂了就没有存下来简直!!!!!!!!!!!!!QAQ 不想再写一遍了...总之是简单贪心. #include <iostream> #include < ...
- jQuery extend扩展String原型
jQuery.extend(String.prototype, { isPositiveInteger:function(){ return (new RegExp(/^[1-9]\d*$/).tes ...