欢迎您访问如何将“客户代码与复杂的对象容器结构”解耦!

如何将“客户代码与复杂的对象容器结构”解耦

更新时间:2023-02-02 20:25:59作者:佚名

说明动机:

* 在面向对象系统中,我们常常会遇到一类具有“容器”特征的对象——即他们在充当对象的同时

* ,又是其他对象的容器。例如:

* class :IBox class :IBox

* { {

* void (){....} void (){....}

* } (){....}

* }

* 如何我们要对这样的对象容器进行处理:

* IBox box=.();

* if(box is )

* {box.(); list=(()box).();...//将面临比较复杂的递归处理}

* else if(box is ){box.();}

* 这样的处理过程显然将其类结构过多的暴露给客户,而且让客户的代码依赖于对象容器复杂的内部实现结构;

* 对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等

* 弊端。如何将“客户代码与复杂的对象容器结构”解耦?让对象容器自己来实现自身的复杂结构,从而使得客

* 户代码就像处理简单对象一样来处理复杂的对象容器

意图:将对象组合成树形结构以表示“部分”与“整体”的层次结构。组合模式是使得用户对单个对象和组合对象的使用一致性。

可适用性:

面向对象的特点

UML图解:

面向对象的特点

示例代码:

namespace Composite  //示例代码
{
///
/// 树容器对象接口
///

public abstract class IBox
{

public abstract void Process();
public abstract void Add(IBox box);
public abstract void Remove(IBox box);
public abstract IBox GetChild(int index);
}

///
/// 单个容器(里面没有子容器)
///

public class SingleBox : IBox
{

public override void Process()
{
//do something processing...

}

public override void Add(IBox box)
{
throw new NotSupportedException();
}

public override void Remove(IBox box)
{
throw new NotSupportedException();
}

public override IBox GetChild(int index)
{
return this;
}
}

///
/// 容器(有子容器)
///

public class ContainerBox : IBox
{
ArrayList boxList = null;

public override void Process()
{
//do process for myself。。
//......
//do process for the box in boxList
foreach (IBox item in boxList)
{
item.Process();
}
}

public override void Add(IBox box)
{
if (boxList == null)
{
boxList = new ArrayList();
}
boxList.Add(box);
}

public override void Remove(IBox box)
{
boxList.Remove(box);
}

public override IBox GetChild(int index)
{
if (boxList == null)
{
throw new NullReferenceException();
}
else if (index <0 || index > boxList.Count)
{
throw new ArgumentOutOfRangeException();
}
return (IBox)boxList[index];
}
}

public class App
{
public static void Main()
{
IBox box = new ContainerBox();
box.Add(new SingleBox());
box.Add(new ContainerBox());

box.Process();//这样客户只需调用Process()方法就足够处理每个子容器了
}
}

}

模式的几个要点:

1、模式采用树形结构来实现普遍存在的对象容器,从而将“一对多”的关系 转化为“一对一”的关系,使得客户代码可以一致地处理对象和对象容器,无需关系处理 的是单个对象,还是组合的对象容器。

2、将“客户代码与复杂的对象容器结构”解耦是模式的核心思想面向对象的特点,解耦之后,客户代码 * 将于纯粹的抽象接口——而非对象容器的复杂内部实现结构——发生依赖关系,从而更能“应对变化”

3、模式中,是将Add和等和对象容器相关的方法定义在了表示抽象对象的类中,还是将其定义在表示对象容器的类中,是一个关乎透明性和安全性的两难问题,需要仔细权衡 。这里有可能违背面向对象的“单一职责原则”,但是对于这种特殊结构,这又是必须付出的代价。ASP.NET 控件的实现在这方面为我们提供了一个很好的示范。

4、模式在具体实现中,可以让父对象中的子对象反向追溯;如果父对象有频繁的遍历要求,可使用缓存技巧改善效率

注:本示例代码是本人学习 C#面向对象设计模式纵横谈系列讲座视频时,跟着李建忠老师一步一步的编写的,在此奉献出来面向对象的特点,仅供大家参考

为您推荐

春日朱熹胜日寻芳泗水滨,无边总是一时春(组图)

等闲识得东风面,万紫千红总是春。等闲识得东风面,万紫千红总是春。第三句“等闲识得东风面”,句中的“识”字承首句中的“寻”字。第四句“万紫千红总是春”,是说这万紫千红的景象全是由春光点染而成的,人们从这万紫千红中认识了春天。这就具体解答了为什么能“等闲识得东风面”。诗人由“寻”而“识”,步步深化,统率全诗的则是一个“新”字。诗中的“泗水”暗喻孔门,“寻芳”暗喻求圣人之道,“东风”暗喻教化,不露说理的痕迹。

2023-02-02 17:25

我会幸福的英文:I##39;llhappy!

我会幸福的英文:文章太长那就听写句子,多听才是王道。你要知道,单词你可能无法一下子记住它的所有意思,但你总会在不同的句子中发现它的奇妙之处。其实语言这东西,学来学去就是为了“交流”二字。【我会幸福的英文怎么写】相关文章:幸福的作文怎么写英文感谢信怎么写请假条的英文怎么写幸福的英文句子英文读书笔记怎么写英文观后感怎么写非常感谢英文怎么写

2023-02-02 16:37

一个求和题目时经常用到的一个方法,你知道吗?

等比数列定义:如果一个数列从第二项起,每一项与它的前一项的比都等于一个常数(不为0),那么,这个数列就叫做等比数列。所以这个题目就是典型的等比数列求和题,在这里G老师分享一个计算等比数列求和题目时经常用到的一个方法。这样我们构造出了一个新数列,分析:这题是等比数列求和,公比是3,共有7项。总结一下,等比数列的一般规律。等比数列中,等比数列的和=(末项x公比-首项)÷(公比-1)

2023-02-02 16:36

务虚与务实是思想方法和工作方法的两个(图)

“变务虚为务实”的口号,显然,这是对“务虚”字面的误解、概念的混淆。务实以务虚为前提,务虚以务实为目的。务虚的工作越深入,务实的效果就越明显。务虚能增添务实的动力。务虚能提升务实的层次。可见,善于务虚是一种能力、一种眼光、一种境界。当务虚不再遭人误解,务实便能真正从中受益。同时,务虚需要实作风,务虚的成效须由务实的效果来检验。

2023-02-02 16:33

等差数列教学目标及重点难点理解的概念,理解并掌握

理解等差数列的概念,理解并掌握等差数列的通项公式,能运用公式解决简单的问题。等差数列的应用例1.1)等差数列8,5,2,······的第20项是几?1)求等差数列3,7,11······的第4项与第10项。在等差数列{an}中,已知a5=10,a12=31,求首项a1与公差d。此等差数列从第几项开始出现负数?2)100是不是等差数列2,9,16······的项?

2023-02-02 16:33

贾平凹真得删去X字了吗?答案很有趣!(图)

很多人喜欢贾平凹的《废都》,对于作品中“此处作者删去×字”印象非常深刻。那么,贾平凹真得删去X字了吗?那么,贾平凹在写《废都》时,删节的部分,真得都写出来了吗?看到这个解释,我们就知道了,贾平凹的删节部分并没有写,如今网络上出现的“此处删掉XX字”,只不过是一些好事之人的狗尾续貂罢了!

2023-02-02 16:33

加载中...