你真的了解Ioc与AOP吗?(1)

转载 2006年06月10日 16:14:00

本系列的全部源代码及二进制文件可以从这里下载:IocInCSharp.rar

你真的了解Ioc与AOP吗?(1)

你真的了解Ioc与AOP吗?(2)

你真的了解Ioc与AOP吗?(3)

你真的了解Ioc与AOP吗?(4)

你真的了解Ioc与AOP吗?(5)


本部分示例代码请参考"src/Step1"、"src/Step2"目录

你真的了解Ioc与AOP吗?我现在还不是很了解,而且越学习越发现自己了解的很少,Ioc与AOP中蕴涵了大量的能量等待我们去开发。在这个系列中,我仅仅利用Sping.net这个框架向大家展示一下Ioc与AOP的强大功能(呵呵,其实写这段话的目的是因为“文章题目”牛皮吹得有点大了,给自己个台阶下罢了)。

在这个系列中一共包含6个案例,从简单到复杂,也是对问题分解、思考和解决的一个过程,它们分别是:(1)类之间的依赖;(2)接口依赖;(3)基于配置文件和Reflection的工厂模式;(4)使用Spring.net实现Ioc;(5)Romoting;(6)利用Ioc在不动一行代码的情况下实现Remoting。为了更好的理解文中的内容,最好顺序阅读。

作为一个应用系统,代码复用至关重要。如果在你的设计中,类与类存在很强的相互关联,那么你会发现在重用这些组件时就存在很严重的问题。在Step1到Step3-Reflection的例子中,我们试图 利用“针对接口编程”以及自己设计的Ioc对系统进行解耦。在Step3到Step5的例子中,我们将利用Spring.net提供的Ioc框架,轻松完成解耦以及系统改造等工作。

一、类之间的依赖

我们的第一个例子主要用于说明程序的基本构造,并且作为一个反面典型,引出为什么要解耦,以及如何下手。在这个例子中,我们将创建三个程序集,分别是MainApp.exe、HelloGenerator.dll以及SayHello.dll。它们之间的关系如下图所示:

HelloGenerator类根据提供的姓名产生一个问候字符串,代码如下:

using System;
namespace IocInCSharp
{
   public class EnHelloGenerator
   {
      public string GetHelloString(string name)
      {
         return String.Format("Hello, {0}", name);
      }
   }
}

SayHello类持有一个对EnHelloGenerator的引用,并负责将生成出来的问候字符串打印出来。

using System;
namespace IocInCSharp
{
   public class SayHello
   {
      private EnHelloGenerator _helloGen;
      public EnHelloGenerator HelloGenerator
      {
         get { return _helloGen; }
         set { _helloGen = value; }
      }
      public void SayHelloTo(string name)
      {
         if(_helloGen != null)
            Console.WriteLine(_helloGen.GetHelloString(name));
         else
            Console.WriteLine("Client.hello is not initialized");
      }
   }
}

MainApp.exe负责完成对象的创建、组装以及调用工作:

using System;
namespace IocInCSharp
{
   public class MainApp
   {
      public static void Main()
      {
         SayHello sayHello = new SayHello();
         sayHello.HelloGenerator = new EnHelloGenerator();
         sayHello.SayHelloTo("zhenyulu");
      }
   }
}

在这个设计中,组件与组件之间、类与类之间存在着紧密的耦合关系。SayHello类中的_helloGen字段类型为EnHelloGenerator,这将导致我们很难给它赋予一个其它的HelloGenerator(例如CnHelloGenerator,用于生成中文问候语)。另外MainApp也严重依赖于SayHello.dll以及HelloGenerator.dll,在程序中我们可以看到类似new SayHello();new EnHelloGenerator();的命令。

这种紧密的耦合关系导致组件的复用性降低。试想,如果想复用SayHello组件,那么我们不得不连同HelloGenerator一同拷贝过去,因为SayHello.dll是依赖与HelloGenerator.dll的。解决这个问题的办法就是“针对抽象(接口)”编程 (依赖倒置原则)。这里的抽象既包括抽象类也包括接口。我不想过多的去谈抽象类和接口的区别,在后续的例子中我们将使用接口。由于接口在进行“动态代理”时仍能保持类型信息,而抽象类可能由于代理的原因导致继承关系的“截断”(如MixIn等)。除此之外,对于单继承的C#语言而言,使用接口可以拥有更大的弹性。

二、接口依赖

既然类之间的依赖导致耦合过于紧密,按照《设计模式》的理论,我们要依赖于接口。但是人们往往发现,仅仅依赖于接口似乎并不能完全解决问题。我们从上面的例子中抽象出接口后,组件间的依赖关系可能变成如下图所示:

经过改造后,SayHello不再依赖于具体的HelloGenerator,而是依赖于IHelloGenerator接口,如此一来,我们可以动态的将EnHelloGenerator或是CnHelloGenerator赋给SayHello,其打印行为也随之发生改变。接口的定义以及改造后的SayHello代码如下(为了节省空间,将代码合并书写):

using System;
namespace IocInCSharp
{
   public interface IHelloGenerator
   {
      string GetHelloString(string name);
   }
   public interface ISayHello
   {
      IHelloGenerator HelloGenerator{ get; set; }
      void SayHelloTo(string name);
   }
   public class SayHello : ISayHello
   {
      private IHelloGenerator _helloGen;
      public IHelloGenerator HelloGenerator
      {
         get { return _helloGen; }
         set { _helloGen = value; }
      }
      public void SayHelloTo(string name)
      {
         if(_helloGen != null)
            Console.WriteLine(_helloGen.GetHelloString(name));
         else
            Console.WriteLine("Client.hello is not initialized");
      }
   }
}

但是我们的MainApp似乎并没有从接口抽象中得到什么好处,从图中看,MainApp居然依赖于三个组件:ICommon.dll、HelloGenerator.dll以及SayHello.dll。这是由于MainApp在这里负责整体的“装配”工作。如果这三个组件中的任何一个发生变化,都将导致MainApp.exe的重新编译和部署。从这个角度来看,似乎“针对接口编程”并没有为我们带来太多的好处。

如果能够将“组件装配”工作抽象出来,我们就可以将MainApp的复杂依赖关系加以简化,从而 进一步实现解耦。为此,我们引入“工厂”模式,并利用配置文件和反射技术,动态加载和装配相关组件。(待续)

相关文章推荐

视频分辨率、像素宽高比、图像比例的概念

视频分辨率:720x576 像素宽高比:1.067, 1.442 图像比例:4:3, 16:9 正常图片像素比为1:1即正方形,所以导入1024*576入16:9项目正好满屏(576...
  • hansel
  • hansel
  • 2012-03-25 23:57
  • 8371

美国人日常生活中五星级句子

熟练地运用英语的一个重要方面就是学习并掌握英语本族者常用的生动、活泼的习语。 1. After  you.你先请。这是一句很常用的客套话,在进/出门,上车得场合你都可以表现一下。 2.I  just ...
  • lang_m
  • lang_m
  • 2006-01-15 23:48
  • 1161

AMD Athlon64 X2 5000

AMD Athlon64 X2 5000 AMD Athlon64 X2 5000+ AM2(盒) 基本参数适用类型 台式CPU ...

八月十八日---晴,太阳

昨天晚上睡得很好,没有失眠虽然昨天在飞翔上遇到宝宝,给宝宝发信息,结果宝宝又不理我~~唉 ,还说我小~~~汗!虽然很郁闷,不过到下午的时候,有一个工作方面的好消息,我是一个很开朗的人,可以说是那种给我...

购物流程借互联网全面“换代”

一种全新的购物方式迅速在京城的白领人群中流行,MM们不再象以前那样直奔大商场购物,而是会先上“便宜你”(www.cheapu.com)——专业导购网站,查阅一下各商场、卖场、品牌正在搞的活动信息,出门...

一封程序员的情书

//仅祝广大编程爱好者早日喜节良缘//也送给我一直暗恋的^^^ //反正这辈子打死她也不上什么CSDN论坛... 茫茫内存里,你我不曾相见; 寥寥代码中,命运注定良缘. 当编译开始,我们齐手共建 --...

ioc AOP深入了解

  • 2014-11-25 16:48
  • 842KB
  • 下载

SpringMVC学习笔记(一)——初步了解IOC,AOP,MVC和ORM

一直以来只专注于工作内容,由于工作经历的关系,一向对于框架不甚重视,认为框架反而束缚了自己的编码,近期由于被大连的某世界500强公司(既然是技术博文,这里不想无意义的黑,所以隐去名字)坑了一把,商定好...

spring、ioc、aop、callback

  • 2012-10-23 21:59
  • 5.18MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)