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
上面2个demo大致说明了如何通过依赖注入对现有的逻辑进行解耦,接下来我们用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 }