First we try, then we trust

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  183 随笔 :: 111 文章 :: 3187 评论 :: 358 引用

一、 合成(Composite)模式

合成模式有时又叫做部分-整体模式(Part-Whole)。合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式可以使客户端将单纯元素与复合元素同等看待。

从和尚的故事谈起

这是小时候我奶奶讲的故事:从前有个山,山里有个庙,庙里有个老和尚在给小和尚讲故事,讲的什么故事呢?从前有个山,山里有个庙……。奶奶的故事要循环多少次,根据你多长时间睡着而定。在故事中有山、有庙、有和尚、有故事。因此,故事的角色有两种:一种里面没有其它角色;另一种内部有其它角色。

对象的树结构

一个树结构由两种节点组成:树枝节点和树叶节点。树枝节点可以有子节点,而一个树叶节点不可以有子节点。除了根节点外,其它节点有且只有一个父节点。

注意:一个树枝节点可以不带任何叶子,但是它因为有带叶子的能力,因此仍然是树枝节点,而不会成为叶节点。一个树叶节点永远不可能带有子节点。


二、 合成模式概述

下图所示的类图省略了各个角色的细节。

 

可以看出,上面的类图结构涉及到三个角色:

  • 抽象构件(Component)角色:这是一个抽象角色,它给参与组合的对象规定一个接口。这个角色给出共有接口及其默认行为。
  • 树叶构件(Leaf)角色:代表参加组合的树叶对象。一个树叶对象没有下级子对象。
  • 树枝构件(Composite)角色:代表参加组合的有子对象的对象,并给出树枝构件对象的行为。

可以看出,Composite类型的对象可以包含其它Component类型的对象。换而言之,Composite类型对象可以含有其它的树枝(Composite)类型或树叶(Leaf)类型的对象。

合成模式的实现根据所实现接口的区别分为两种形式,分别称为安全模式和透明模式。合成模式可以不提供父对象的管理方法,但合成模式必须在合适的地方提供子对象的管理方法(诸如:add、remove、getChild等)。

透明方式

作为第一种选择,在Component里面声明所有的用来管理子类对象的方法,包括add()、remove(),以及getChild()方法。这样做的好处是所有的构件类都有相同的接口。在客户端看来,树叶类对象与合成类对象的区别起码在接口层次上消失了,客户端可以同等同的对待所有的对象。这就是透明形式的合成模式。

这个选择的缺点是不够安全,因为树叶类对象和合成类对象在本质上是有区别的。树叶类对象不可能有下一个层次的对象,因此add()、remove()以及getChild()方法没有意义,是在编译时期不会出错,而只会在运行时期才会出错。

安全方式

第二种选择是在Composite类里面声明所有的用来管理子类对象的方法。这样的做法是安全的做法,因为树叶类型的对象根本就没有管理子类对象的方法,因此,如果客户端对树叶类对象使用这些方法时,程序会在编译时期出错。

这个选择的缺点是不够透明,因为树叶类和合成类将具有不同的接口。

这两个形式各有优缺点,需要根据软件的具体情况做出取舍决定。


三、 安全式的合成模式的结构

安全式的合成模式要求管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件中。

 

这种形式涉及到三个角色:

  • 抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。在安全式的合成模式里,构件角色并不是定义出管理子对象的方法,这一定义由树枝构件对象给出。
  • 树叶构件(Leaf)角色:树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。
  • 树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝对象给出所有的管理子对象的方法,如add()、remove()、getChild()等。


四、 安全式的合成模式实现

以下示例性代码演示了安全式的合成模式代码:

// Composite pattern -- Structural example  
using System;
using System.Text;
using System.Collections;

// "Component"
abstract class Component
{
  
// Fields
  protected string name;

  
// Constructors
  public Component( string name )
  
{
    
this.name = name;
  }


  
// Operation
  public abstract void Display( int depth );
}


// "Composite"
class Composite : Component
{
  
// Fields
  private ArrayList children = new ArrayList();

  
// Constructors
  public Composite( string name ) : base( name ) {}

  
// Methods
  public void Add( Component component )
  
{
    children.Add( component );
  }

  
public void Remove( Component component )
  
{
    children.Remove( component );
  }

  
public override void Display( int depth )
  
{
    Console.WriteLine( 
new String( '-', depth ) + name );

    
// Display each of the node's children
    foreach( Component component in children )
      component.Display( depth 
+ 2 );
  }

}


// "Leaf"
class Leaf : Component
{
  
// Constructors
  public Leaf( string name ) : base( name ) {}

  
// Methods
  public override void Display( int depth )
  
{
    Console.WriteLine( 
new String( '-', depth ) + name );
  }

}


/// <summary>
/// Client test
/// </summary>

public class Client
{
  
public static void Main( string[] args )
  
{
    
// Create a tree structure
    Composite root = new Composite( "root" );
    root.Add( 
new Leaf( "Leaf A" ));
    root.Add( 
new Leaf( "Leaf B" ));
    Composite comp 
= new Composite( "Composite X" );

    comp.Add( 
new Leaf( "Leaf XA" ) );
    comp.Add( 
new Leaf( "Leaf XB" ) );
    root.Add( comp );

    root.Add( 
new Leaf( "Leaf C" ));

    
// Add and remove a leaf
    Leaf l = new Leaf( "Leaf D" );
    root.Add( l );
    root.Remove( l );

    
// Recursively display nodes
    root.Display( 1 );
  }

}


五、 透明式的合成模式结构

与安全式的合成模式不同的是,透明式的合成模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定的接口。

 

这种形式涉及到三个角色:

  • 抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象规定一个接口,规范共有的接口及默认行为。
  • 树叶构件(Leaf)角色:代表参加组合的树叶对象,定义出参加组合的原始对象的行为。树叶类会给出add()、remove()以及getChild()之类的用来管理子类对对象的方法的平庸实现。
  • 树枝构件(Composite)角色:代表参加组合的有子对象的对象,定义出这样的对象的行为。


六、 透明式的合成模式实现

以下示例性代码演示了安全式的合成模式代码:

// Composite pattern -- Structural example  

using System;
using System.Text;
using System.Collections;

// "Component"
abstract class Component
{
  
// Fields
  protected string name;

  
// Constructors
  public Component( string name )
  
this.name = name; }

  
// Methods
  abstract public void Add(Component c);
  
abstract public void Remove( Component c );
  
abstract public void Display( int depth );
}


// "Composite"
class Composite : Component
{
  
// Fields
  private ArrayList children = new ArrayList();

  
// Constructors
  public Composite( string name ) : base( name ) {}

  
// Methods
  public override void Add( Component component )
  
{ children.Add( component ); }
  
  
public override void Remove( Component component )
  
{ children.Remove( component ); }
  
  
public override void Display( int depth )
  

    Console.WriteLine( 
new String( '-', depth ) + name );

    
// Display each of the node's children
    foreach( Component component in children )
      component.Display( depth 
+ 2 );
  }

}


// "Leaf"
class Leaf : Component
{
  
// Constructors
  public Leaf( string name ) : base( name ) {}

  
// Methods
  public override void Add( Component c )
  
{ Console.WriteLine("Cannot add to a leaf"); }

  
public override void Remove( Component c )
  
{ Console.WriteLine("Cannot remove from a leaf"); }

  
public override void Display( int depth )
  
{ Console.WriteLine( new String( '-', depth ) + name ); }
}


/// <summary>
/// Client test
/// </summary>

public class Client
{
  
public static void Main( string[] args )
  
{
    
// Create a tree structure
    Composite root = new Composite( "root" );
    root.Add( 
new Leaf( "Leaf A" ));
    root.Add( 
new Leaf( "Leaf B" ));
    Composite comp 
= new Composite( "Composite X" );

    comp.Add( 
new Leaf( "Leaf XA" ) );
    comp.Add( 
new Leaf( "Leaf XB" ) );
    root.Add( comp );

    root.Add( 
new Leaf( "Leaf C" ));

    
// Add and remove a leaf
    Leaf l = new Leaf( "Leaf D" );
    root.Add( l );
    root.Remove( l );

    
// Recursively display nodes
    root.Display( 1 );
  }

}


七、 使用合成模式时考虑的几个问题

  1. 明显的给出父对象的引用。在子对象里面给出父对象的引用,可以很容易的遍历所有父对象。有了这个引用,可以方便的应用责任链模式。
  2. 在通常的系统里,可以使用享元模式实现构件的共享,但是由于合成模式的对象经常要有对父对象的引用,因此共享不容易实现。
  3. 有时候系统需要遍历一个树枝结构的子构件很多次,这时候可以考虑把遍历子构件的结果暂时存储在父构件里面作为缓存。
  4. 关于使用什么数据类型来存储子对象的问题,在示意性的代码中使用了ArrayList,在实际系统中可以使用其它聚集或数组等。
  5. 客户端尽量不要直接调用树叶类中的方法,而是借助其父类(Component)的多态性完成调用,这样可以增加代码的复用性。


八、 和尚的故事


九、 一个实际应用Composite模式的例子

下面是一个实际应用中的程序,演示了通过一些基本图像元素(直线、园等)以及一些复合图像元素(由基本图像元素组合而成)构建复杂的图形树的过程。

// Composite pattern -- Real World example  

using System;
using System.Collections;

// "Component"
abstract class DrawingElement
{
  
// Fields
  protected string name;

  
// Constructors
  public DrawingElement( string name )
  
this.name = name; }
 
  
// Operation
  abstract public void Display( int indent );
}


// "Leaf"
class PrimitiveElement : DrawingElement
{
  
// Constructors
  public PrimitiveElement( string name ) : base( name ) {}

  
// Operation
  public override void Display( int indent )
  
{
    Console.WriteLine( 
new String( '-', indent ) + 
      
" draw a {0}", name );
  }

}


// "Composite"
class CompositeElement : DrawingElement
{
  
// Fields
  private ArrayList elements = new ArrayList();
 
  
// Constructors
  public CompositeElement( string name ) : base( name ) {}

  
// Methods
  public void Add( DrawingElement d )
  
{ elements.Add( d ); }

  
public void Remove( DrawingElement d )
  
{ elements.Remove( d ); }

  
public override void Display( int indent )
  
{
    Console.WriteLine( 
new String( '-', indent ) +
      
"" + name );

    
// Display each child element on this node
    foreach( DrawingElement c in elements )
      c.Display( indent 
+ 2 );
  }

}

 
/// <summary>
///  CompositeApp test
/// </summary>

public class CompositeApp
{
  
public static void Main( string[] args )
  
{
    
// Create a tree structure
    CompositeElement root = new  
      CompositeElement( 
"Picture" );
    root.Add( 
new PrimitiveElement( "Red Line" ));
    root.Add( 
new PrimitiveElement( "Blue Circle" ));
    root.Add( 
new PrimitiveElement( "Green Box" ));

    CompositeElement comp 
= new  
      CompositeElement( 
"Two Circles" );
    comp.Add( 
new PrimitiveElement( "Black Circle" ) );
    comp.Add( 
new PrimitiveElement( "White Circle" ) );
    root.Add( comp );

    
// Add and remove a PrimitiveElement
    PrimitiveElement l = new PrimitiveElement( "Yellow Line" );
    root.Add( l );
    root.Remove( l );

    
// Recursively display nodes
    root.Display( 1 );
  }

}

合成模式与很多其它模式都有联系,将在后续内容中逐步介绍。


参考文献:
阎宏,《Java与模式》,电子工业出版社
[美]James W. Cooper,《C#设计模式》,电子工业出版社
[美]Alan Shalloway  James R. Trott,《Design Patterns Explained》,中国电力出版社
[美]Robert C. Martin,《敏捷软件开发-原则、模式与实践》,清华大学出版社
[美]Don Box, Chris Sells,《.NET本质论 第1卷:公共语言运行库》,中国电力出版社

0
0
(请您对文章做出评价)
« 上一篇:设计模式随笔-从“有病”说起(工厂模式前传)
» 下一篇:C#设计模式(11)-Composite Pattern
posted on 2004-09-10 15:03 吕震宇 阅读(14311) 评论(39)  编辑 收藏 网摘 所属分类: 设计模式

评论

#1楼 2004-09-10 16:43 灵感之源
说真的,我还真的不了解什么是复合模式....
  回复  引用    

#2楼 2004-09-10 17:57 飞刀
老大,你这不是照抄《Java与模式》啊,呵呵。
老道士,就被你改成了老和尚啊,哈哈:)

《Java与模式》是本好书,不过他还只是告诉了你这个概念,如果你要知道模式在工程中具体怎么用,还得多看别人的源代码:)

  回复  引用    

#3楼 2004-09-10 18:02 吕震宇
@飞刀

是呀,这是我的教案呀。市面上没有好的C#设计模式书,所以只能取材于《Java与模式》了。其实很多例子还来自于一个网站:

http://www.dofactory.com/Patterns/Patterns.aspx

我只是做了个裁缝,缝补到了一起。上面的参考资料倒是都参考了.

  回复  引用    

#4楼 2004-09-10 18:07 吕震宇
@飞刀

我在平时的项目开发中倒是应用了些模式,只是没用过所有23种模式,虽有感触,可不好意思拿出手。况且《Java与模式》写的太好了。

  回复  引用    

#5楼 2004-09-10 20:48 kwklover
@吕震宇 老大
呵呵,我自己也买了本《C#设计模式》的书,但还怎么看过

到是你的C#设计模式系列。我倒看完了,你写的比书上的好懂
一些
谢谢了

希望你能早点发完你系列文章,期待ing  


  回复  引用    

#6楼 2004-09-11 14:04 飞刀
@吕震宇

既然你接受Java,就多看点java中比较NB的源代码吧。
总得还说那本书为了写的好懂,所以写的就很简单,我现在的感觉那书就告诉你有这么一回事,有时候用的时间也写的简单。

你要是看了别人的源代码,你就发现原来还可以这么用啊:)

推荐你先看Swing系列的源代码。

  回复  引用    

#7楼 2004-09-11 14:50 寒枫天伤
不错不错:)

写得不错,虽然“借鉴”了一下,不过,写得也不错,只要通俗易懂,怎么写都行。

  回复  引用    

#8楼 2004-09-11 15:05 寒枫天伤
"从和尚的故事谈起"

补充一下:
人的大脑对事物反应需要一种刺激来维护,但外界变化到达一种重复或相对静止的状态时,那么人的大脑会出现疲软,人的精力会下降,效率自然也会下降,在持续一段时间之后,如果外界出现变化,而人脑此时对外界已经模式化,所以就无法反应外界的变化。此时,人脑与其说是忽略了某些东西,不如说是根据这些东西就没反应到大脑中。
保持清醒的办法就是不断地对大脑进行刺激,随时让大脑处于对外界变化的敏感捕捉之下,这样才能敏捷地捕捉变化。
同样的,“模式”的思想也一样,它提供了一种让你思考的途径,掌握一些有效的模式化的方法,可以有效地提高效率,这根用筷子夹东西一样,要牵动身体的100多块肌肉。但又有几个人想过,自己夹东西的办法是否是最有效率的呢?这是一个“习惯”问题。
创新性的思维不一定是要开辟新的领域,寻找已有领域中的遗漏部分,可以发现很多有价值的东西,以前是因为这样或那样的原因,在当时的条件下,还没有来得及发现,就停止了,实际上,它是一条可行的路,路上由于现有条件的原因,会充满各种机遇与挑战。

....:)我没跑题,明白人,一看就知道我在说什么。

  回复  引用    

#9楼 2004-09-12 17:47 吕震宇
从北京回来了。这两天帮亲戚搬家,累死了。

回来看到不少关心和鼓励的话,先一并都谢了。《C#设计模式》系列的文章我还会写下去,当然也少不了抄《Java与模式》的内容。不过所谓“天下文章一大抄,看你会抄不会抄”。我尽量站在一个C#学习者的角度,“抄”的更有价值,更通俗易懂,我的目的也达到了。相信我这学期教的学生会满意的,也希望关注这个系列的网友满意。

@飞刀

谢谢你的建议。其实我接触Java并不多,而且大多从.net的角度审视Java,有一定的局限性。学习Java也有一部分原因是因为读的《设计模式》、《代码重构》、《企业模式》、《分析模式》等大部分例子是用Java写的。其实我在大学主要方向是数据库方向。写代码主要是因为项目需要。计算机范围太广了,有时候我认为自己连数据这方面都不能灵活应用,再扩展空间恐怕吃不消。

我有个建议,不知飞刀是否愿意能在Java Swing方面发表一系列随笔,从Swing的角度深入阐释设计模式以及相关技术呢?我会作为一个热心读者随时关注的!

  回复  引用    

#10楼 2004-09-13 08:44 寒枫天伤
晕。

你究竟是去北京还是从北京回来?

  回复  引用    

#11楼 2004-09-13 08:48 吕震宇
呵呵,去北京帮人搬家,然后又回来了。
  回复  引用    

#12楼 2004-09-19 08:14 luoluo[未注册用户]
全部看完,我是初学者,手上有一本James W.Cooper的《c# Design Patterns: A Tutorial》影印版,看的感觉很迷糊,这里的文章和讨论让我受益了,在此表示感谢,并期望有新的文章。
  回复  引用    

#13楼 2004-09-19 12:59 吕震宇
在TechEd2004会场上用Acer笔记本上网, 感觉不错. 我明天回去,设计模式系列也会继续的. 很多天没有更新BLOG了...
  回复  引用    

#14楼 2004-09-20 16:49 jcaomao
其实我觉得编程的很多东西都应该从浅到深来学,我以前看.net的很多东西都看不懂,后来都是从一些比较简单的文章或者教程看懂一些,然后才深入进去,慢慢的懂的越来越多了。

如果直接看一些比较高深的东西往往会对某些知识产生恐惧,觉得自己很笨根本就看不懂,其实是作者写的不得当,没有从读者的角度来考虑问题,很多东西的原理其实很简单的,让他们一写就云山雾罩的了,显着他们的水平很高。

就像我以前学win32汇编看了很多次也看不懂,最后差点放弃,后来看到 罗云斌 的那本书以后,很多都明白了,原来汇编入门也不是这么难啊。

  回复  引用    

#15楼 2004-09-20 18:12 吕震宇
深有同感,在读一本书的时候,我希望这本书中40%的东西是我知道的,30%的东西是我不很清楚的,另外30%的东西是我不知道的,这样才能引起共鸣,感觉收获颇丰。

如果是“大师”级人物的著作,有时候似乎更容易理解。因为只有真正明白的人才能写明白,让大家都明白。 :)

  回复  引用    

#16楼 2004-09-20 23:12 luoluo[未注册用户]
我想起以前我们院长的话,国外很多国家的基础科学的教科书的编纂都是很重要的事情,都是由这些学科的权威的科学家编写的,而我们国家却很少。

呵呵,扯远了。

  回复  引用    

#17楼 2004-10-26 21:52 lsq
请问版主:
抽象构件(Component)角色与树枝构件(Composite)角色之间是应该是聚合关系而不是组合关系。因为树技可能没有子结点啊。。

  回复  引用    

#18楼[楼主] 2004-10-27 00:15 吕震宇      
@lsq

谢谢指教!上面的图我确实画错了。有时间我会更正过来的。这一方面的原因是Visio没有一个明确的图标区分聚合关系与组合关系,必须手工设置线形,我偷懒了,没有去设置。呵呵,不好意思。

  回复  引用  查看    

#19楼[楼主] 2004-11-09 08:38 吕震宇      
聚合关系的图形表述问题终于修正过来了。呵呵,耽误了很长时间,真对不住大家。
  回复  引用  查看    

#20楼 2004-11-09 14:32 mill2002
很忙吧~
关注你的下一篇PATTERN文章 :)

  回复  引用    

#21楼 2005-03-15 14:41 lrabby168      
我是初学者,对于什么是聚合关系什么又是组合关系不是太清楚。

如果有时间,给我解释一下吧。

多谢。

  回复  引用  查看    

我只想对你说,如果做你的学生,那太幸福了.
大学的老师就知道读课本,如果我能早看到这些出自于老师的文章就好了.
多谢!你写的比C#设计模式这本书写的好懂,决定看java与模式,虽然我只会.net.

  回复  引用    

#23楼 2006-04-04 10:57 Dabay      
我才开始学习设计模式 在网上一搜索来到这里
吕老师写得真的很好啊 佩服的很 谢谢你的讲解 ^_^

  回复  引用  查看    

搂主在透明模式的示例代码中没有完全体现出透明模式的思想。在创建对象时因该使用Component。
public static void Main(string[] args)
{
// Create a tree structure

//Composite root = new Composite("root");
Component root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));

//Composite comp = new Composite("Composite X");
Component comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);

root.Add(new Leaf("Leaf C"));

// Add and remove a leaf
Leaf l = new Leaf("Leaf D");
root.Add(l);
root.Remove(l);

// Recursively display nodes
root.Display(1);
}
假如此时对象的创建是通过如下的方法来实现的。
Component root = Factory.Get(...);
root.add(new leaf(...));
此时如果是安全模式用户在进行add前需要事先判断root的类型。
if(root is Composite) { add ...}
而改为透明模式时就消除了上述问题。正如楼主所说的“客户端可以同等的对待所有的对象。”

  回复  引用    

楼上的说得有道理,所谓透明就是客户端完全不知道自己处理的对象是什么类型的,只知道是一个接口,或者抽象类。如果通过工厂获得的,那么使用楼上的方法显然更好。
  回复  引用    

#26楼 2006-07-15 18:05 xxm_hl[未注册用户]
吕老师我想问个问题,如果把您写的这些设计模式的文章都能看懂了。你估记一下那将是个什么水平了。觉的看你的这些文章好容易懂,我自己买了一本C#的设计模式的书,我却根本就看不懂(Steven John Metsker写,电力出版社出版的),要是您看这过本书,可以拿您的文章和这本书的内容对比一下吗?我感觉两者之间的区别太大了。好像一个是VB,一个是汇编的感觉了
  回复  引用    

#27楼 2006-09-30 14:59 msjqad[未注册用户]
好长时间没有继续的看设计模式了。
不过我一定会读完
吕老师通俗易懂的讲解给了我不少帮助

  回复  引用    

#28楼 2007-01-25 16:52 PH580[未注册用户]
谢谢让我省了买书的钱了!!!!!!!!!
  回复  引用    

#29楼 2007-04-28 11:10 Eric[未注册用户]
学习了。简单的应用还性。不知道怎么做大项目。呵呵。
  回复  引用    

#30楼 2007-05-28 12:46 lfWang[未注册用户]
不知道 Composite Pattern 有什么用啊?
  回复  引用    

#31楼 2009-05-11 14:33 大同      
tks
  回复  引用  查看    

你寫的一系列真是不錯容易懂~~
我也開發系統多年了,最近因工作需要,
所以開始研究C#的物件導向(你們叫做面向對象),
台灣這邊對於設計模式的相關網站不多,
你這個網站我在這邊連過來有點慢,
看你的文章之後有感於,也許我也應該在台灣這邊推廣一下,
所以我想引用你的設計模式相關文章,
然後編排為台灣人容易了解的說法,
不知是否到時可以讓我引用。

謝謝

  回复  引用    

#33楼[楼主] 2009-08-07 22:08 吕震宇      
@gdrs5897

你好!

其实我博客中的文章只是上课给学生讲课用的“课件”。而且很多东西我都照搬自《Java与模式》一书,只不过改为C#版而已。所以还是不要引用为好,毕竟不全是我的东西。另外有些东西也来自一些英文网站,在设计模式系列前几章参考文献中有引用。建议抽空读一读《Java与模式》一书,也是我在设计模式系列后面写的参考文献中的几本书,其实这些书都比我的东西强很多。

很长时间没有写博客了,没想到4、5年前的东西还能产生影响,网络力量太大了。每篇文章后面的讨论集合了网友的众多想法,我感觉也很值得学习。另外《设计模式随笔》系列的东西全是我自己写的,你完全可以拿去用,没有任何问题。

吕震宇

  回复  引用  查看    

是呀,吕老师,网络的力量很大,最近在学习设计模式,在google上搜了下C#设计模式,没想到,第一页第一位就是熟悉的First we try, then we trust,让我很兴奋的又一次打开,自毕业以后,已经从事软件开发行业4个月,4个月收获的东西很多,但是又发现要学习的东西很多,但是我还是不明白设计模式到底用来干什么的,最近在用三层架构做一个北京的项目,发现了自己很多的漏洞,只好查漏补缺了,作为信管来说,学习计算机知识方面确实太少太少,光靠学校学的那点东西,远远不能满足以后工作的需要,但是不可否认的是,吕老师在我的人生道路上起到了抛砖引玉的作用。有时候在想什么时候才能达到吕老师的水平,是不是时间到了自然水平就到了,后来想想,如果自己不努力不去学习,哪怕过10年20年还是原地踏步,如果想达到吕老师的水平只能多学多练,1天当2天使,呵呵,我们毕业了,很想再听吕老师的一讲课,真的非常期望,听吕老师的课受益匪浅,每次上课我都尽量让自己聚精会神努力记住每一句您曾经说过的话,哪怕是当时不懂也要记住,以便日后想起来。还有吕老师,我在翻阅我照的相片的时候发现个问题,在最后一次聚餐的时候,发现,你喝的酒全是酸梅汤'囧'唉。我们信管的39个人会努力的。谢谢老师的栽培之恩。
  回复  引用    

我最近在温习设计模式,第一时间就想到了吕老师的这个系列。今天刚温习到抽象工厂。 希望老师能回来继续写更多的好文章。

BTW:我不是老师学校的学生,我是老师博客园的学生。 :)

  回复  引用