Robotlegs2 学习笔记 -- SwiftSuspenders 2.x (1)


Swiftsuspenders2 是一个基于元数据(metadata)的IOC(控制反转,inversion of control)的AS3的解决方案。反转控制又被称依赖注射(Dependency Injection),也就是将依赖先剥离,然后在适当时候再注射进入。它是一种降低耦合度的程序设计模式其核心原则是高层模块不应依赖于低层模块,他们都应该依赖于抽象。抽象不依赖细节,细节依赖抽象,它通过将对象的创建过程解耦出来来降低对象间的依赖关系。IOC的设计目标是不直接创建对象,但是描述对象的创建方式,在代码中不直接链接对象和服务,通过配置的方式描述哪一种组件需要哪一些服务,然后在ioc容器中负责自动将对象服务和需要使用他们的地方进行链接。下面我们通过一个简单的例子,先了解一下如何利用依赖注入进行解耦。

关于依赖注入

当我们需要进行一个发送消息或者邮件的流程时 我们可能会写如下代码(demo0):

 1 package  demo0
 2 {
 3     /**
 4      * ...
 5      * @author titi
 6      */
 7     public class Mail 
 8     {
 9         public var Title:String;
10         
11         public function Send():void
12         {
13             trace(" Send Mail:"+Title);
14         }
15         
16         public function Mail(title:String) 
17         {
18             Title = title;
19         }
20         
21     }
22 
23   }
24   
25   
26 package  demo0
27 {
28     /**
29      * ...
30      * @author titi
31      */
32     public class Notification 
33     {
34         private var _email:Mail;
35         public function Notification() 
36         {
37             _email = new Mail("测试邮件1");
38         }
39         
40         
41         public function PromotionalNotification():void
42         {
43             _email.Send();
44         }
45     }
46 
47   }
48   
49   
50 package demo0
51 {
52     import flash.display.Sprite;
53     import flash.events.Event;
54     
55     /**
56      * ...
57      * @author titi
58      */
59     public class Main0 extends Sprite 
60     {
61         
62         public function Main0():void 
63         {
64             if (stage) init();
65             else addEventListener(Event.ADDED_TO_STAGE, init);
66         }
67         
68         private function init(e:Event = null):void 
69         {
70             removeEventListener(Event.ADDED_TO_STAGE, init);
71             // entry point
72             var notificatoin:Notification = new Notification();
73             notificatoin.PromotionalNotification();
74         }
75         
76     }
77     
78   }

这里Mail和其控制器Notification 是直接关联的,控制器依赖Mail对象。通过抽象Mail 可以进行解耦降低Notification和Mail的耦合度。

 1 package demo1 
 2 {
 3     
 4     /**
 5      * ...
 6      * @author titi
 7      */
 8     public interface IMsg 
 9     {
10         function set Title(value:String):void;
11         
12         function get Title():String;
13         
14         function Send():void;
15     }
16     
17 }
18   
19 package  demo1
20 {
21     /**
22      * ...
23      * @author titi
24      */
25     public class Mail implements  IMsg
26     {
27         public var _Title:String;
28         
29         public function Send():void
30         {
31             trace(" Send Mail:"+Title);
32         }
33         
34         public function Mail(title:String) 
35         {
36             _Title = title;
37         }
38         
39         /* INTERFACE demo1.IMsg */
40         
41         public function set Title(value:String):void 
42         {
43             _Title = value;
44         }
45         
46         public function get Title():String 
47         {
48             return _Title;
49         }
50         
51     }
52 
53 }
54 
55  package  demo1
56 {
57     /**
58      * ...
59      * @author titi
60      */
61     public class Notification 
62     {
63         private var _email:IMsg;
64 
65         public function PromotionalNotification():void
66         {
67             _email.Send();
68         }
69     }
70 
71 }

抽象后 可以通过四种方式(注入点Notification 中注入IMail对应的具体的Mail 分别是

 

1、构造函数注入

 1 package  demo1
 2 {
 3     /**
 4      * ...
 5      * @author titi
 6      */
 7     public class Notification 
 8     {
 9         private var _email:IMsg;
10         public function Notification(email:IMsg) 
11         {
12             _email = email;
13         }
14         
15         
16         public function PromotionalNotification():void
17         {
18             _email.Send();
19         }
20     }
21 
22 }

2、方法注入

 1 package  demo1
 2 {
 3     /**
 4      * ...
 5      * @author titi
 6      */
 7     public class Notification3
 8     {
 9         private var _email:IMsg;
10         
11         public function Notification3() 
12         {
13             
14         }
15         
16         
17         public function PromotionalNotification(mail:IMsg):void
18         {
19             mail.Send();
20         }
21     }
22 
23 }

3、属性注入

 1 package  demo1
 2 {
 3     /**
 4      * ...
 5      * @author titi
 6      */
 7     public class Notification2
 8     {
 9         private var _email:IMsg;
10         
11         public function Notification2() 
12         {
13             
14         }
15         
16         
17         public function PromotionalNotification():void
18         {
19             _email.Send();
20         }
21 
22         //提供供外部注入Set属性
23         public function set email(value:IMsg):void 
24         {
25             _email = value;
26         }
27     }
28 
29 }

4、变量注入

 1 package  demo1
 2 {
 3     /**
 4      * ...
 5      * @author titi
 6      */
 7     public class Notification4
 8     {
 9         /**
10          * 公共变量提供抽象注入
11          */
12         public var _email:IMsg;
13         
14         public function Notification4() 
15         {
16             
17         }
18         
19         
20         public function PromotionalNotification():void
21         {
22             _email.Send();
23         }
24 
25     }
26 
27 }

在Demo1中我们用如下代码来进行显示的抽象注入:

 1 package demo1
 2 {
 3     import flash.display.Sprite;
 4     import flash.events.Event;
 5     
 6     /**
 7      * ...
 8      * @author titi
 9      */
10     public class Main1 extends Sprite 
11     {
12         
13         public function Main1():void 
14         {
15             if (stage) init();
16             else addEventListener(Event.ADDED_TO_STAGE, init);
17         }
18         
19         private function init(e:Event = null):void 
20         {
21             removeEventListener(Event.ADDED_TO_STAGE, init);
22             // entry point
23             
24             //构造依赖
25             var notificatoin:Notification = new Notification(new Mail("测试邮件1"));
26             notificatoin.PromotionalNotification();
27             //属性依赖
28             var notificatoin2:Notification2 = new Notification2();
29             notificatoin2.email = new Mail("测试邮件2");
30             notificatoin2.PromotionalNotification();
31             //方法依赖
32             var notificatoin3:Notification3 = new Notification3();
33             notificatoin3.PromotionalNotification(new Mail("测试邮件3"));
34             //变量依赖
35             var notificatoin4:Notification4 = new Notification4();
36             notificatoin4._email=new Mail("测试邮件4")
37             notificatoin4.PromotionalNotification();
38         }
39         
40     }
41     
42 }

执行后输出如下:

1  Send Mail:测试邮件1
2  Send Mail:测试邮件2
3  Send Mail:测试邮件3
4  Send Mail:测试邮件4

上面2demo大致说明了如何通过依赖注入对现有的逻辑进行解耦,接下来我们用Swiftsuspenders2框架来快速实现上述的demo1作为对Swiftsuspenders2框架的入门详细参考如下demo2代码。

 

  1 package  demo2
  2 {
  3     /**
  4      * ...
  5      * @author titi
  6      */
  7     
  8     [Inject(name="email1")]
  9     public class Notification 
 10     {
 11         private var _email:IMsg;
 12         public function Notification(email:IMsg) 
 13         {
 14             _email = email;
 15         }
 16         
 17         
 18         public function PromotionalNotification():void
 19         {
 20             _email.Send();
 21         }
 22     }
 23 
 24 }
 25 
 26 package  demo2
 27 {
 28     /**
 29      * ...
 30      * @author titi
 31      */
 32     public class Notification2
 33     {
 34         private var _email:IMsg;
 35         
 36         public function Notification2() 
 37         {
 38             
 39         }
 40         
 41         
 42         public function PromotionalNotification():void
 43         {
 44             _email.Send();
 45         }
 46         
 47         public function get email():IMsg 
 48         {
 49             return _email;
 50         }
 51         
 52         [Inject(name="email2")]
 53         public function set email(value:IMsg):void 
 54         {
 55             _email = value;
 56         }
 57     }
 58 
 59 }
 60 package  demo2
 61 {
 62     /**
 63      * ...
 64      * @author titi
 65      */
 66     public class Notification3
 67     {
 68         private var _email:IMsg;
 69         
 70         public function Notification3() 
 71         {
 72             
 73         }
 74         
 75         [Inject(name = "email3")]
 76         public function inject(mail:IMsg):void
 77         {
 78             _email = mail;
 79         }
 80         
 81         public function PromotionalNotification():void
 82         {
 83             _email.Send();
 84         }
 85     }
 86 
 87 }
 88 
 89 package  demo2
 90 {
 91     /**
 92      * ...
 93      * @author titi
 94      */
 95     public class Notification4
 96     {
 97         /**
 98          * 公共变量提供抽象注入
 99          */
100         
101         [Inject(name = "email4")]
102         public var _email:IMsg;
103         
104         public function Notification4() 
105         {
106             
107         }
108         
109         
110         public function PromotionalNotification():void
111         {
112             _email.Send();
113         }
114 
115     }
116 
117 }
118 
119 package demo2
120 {
121     import flash.display.Sprite;
122     import flash.events.Event;
123     import org.swiftsuspenders.Injector;
124     
125     /**
126      * ...
127      * @author titi
128      */
129     public class Main2 extends Sprite 
130     {
131         
132         public function Main2():void 
133         {
134             if (stage) init();
135             else addEventListener(Event.ADDED_TO_STAGE, init);
136         }
137         
138         private function init(e:Event = null):void 
139         {
140             removeEventListener(Event.ADDED_TO_STAGE, init);
141             // entry point
142             
143             //申明注入器
144             var injector:Injector = new Injector();
145             
146             injector.map(IMsg, "email1").toValue(new Mail("测试邮件1"));
147             injector.map(IMsg, "email2").toValue(new Mail("测试邮件2"));
148             injector.map(IMsg, "email3").toValue(new Mail("测试邮件3"));
149             injector.map(IMsg, "email4").toValue(new Mail("测试邮件4"));
150             
151             (injector.instantiateUnmapped(Notification) as Notification).PromotionalNotification();
152             (injector.instantiateUnmapped(Notification2) as Notification2).PromotionalNotification();
153             (injector.instantiateUnmapped(Notification3) as Notification3).PromotionalNotification();
154             (injector.instantiateUnmapped(Notification4) as Notification4).PromotionalNotification();
155         }
156         
157     }
158     
159 }