天天看點

代理模式 & 裝飾器模式 (Proxy & Decorator)

代理模式和裝飾器模式雖然概念上差別很大,但是在實作時卻又比較相似。

代理模式從概念上講,就是我想通路一個服務,但是我卻不需要知道真正給我提供服務的對象,我隻要通路能提供給我服務的代理對象就可以了。

裝飾器模式從概念上講,就是要裝飾一個對象,隻要把這個對象通過裝飾器的構造函數傳入,裝飾器會做一些額外的裝飾。因為裝飾器也實作了對象實作的接口,是以就可以像操作對象一樣操作裝飾器。

代理模式的類圖:

代理模式 & 裝飾器模式 (Proxy & Decorator)

Interface Subject:

package com.mode.interfaces
{
	public interface Subject
	{
	     function doAction():void;
	}
}      

 RealSubject

package com.mode.concrete
{
	import com.mode.interfaces.Subject;
	
	public class RealSubject implements Subject
	{
		public function RealSubject()
		{
		}
		
		public function doAction():void
		{
			trace("Real Subject do Action");
		}
	}
}      

 Proxy:

package com.mode.proxy
{
	import com.mode.concrete.RealSubject;
	import com.mode.interfaces.Subject;
	
	public class Proxy implements Subject
	{
		private var subject:Subject;		
		public function doAction():void
		{
			if(subject == null)
			{
				subject = new RealSubject();
			}
			doSomeActionBefore();
			subject.doAction();
			doSomeActionAfter();
			
		}
		
		private function doSomeActionBefore():void
		{
			trace("Proxy do some action before");
		}
		
		private function doSomeActionAfter():void
		{
			trace("Proxy do some action after");
		}
	}
}      

 Client test:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
	<fx:Script>
		<![CDATA[
			import com.mode.interfaces.Subject;
			import com.mode.proxy.Proxy;
			protected function button1_clickHandler(event:MouseEvent):void
			{
				var subject:Subject = new com.mode.proxy.Proxy();
				subject.doAction();
				/* output: 
				Proxy do some action before
				Real Subject do Action
				Proxy do some action after 
				*/
			}
		]]>
	</fx:Script>
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<s:Button label="Proxy Demo" click="button1_clickHandler(event)"/>
</s:Application>
      

 你會發現我真正通路的是RealSubject的doAction,但是Proxy屏蔽了它并做了一些額外的服務。

代理模式 &amp; 裝飾器模式 (Proxy &amp; Decorator)

Interface of Component:

package com.mode.interfaces
{
	public interface Component
	{
		function operation():void;
	}
}      

 ConcreteComponent:

package com.mode.concrete
{
	import com.mode.interfaces.Component;
	
	public class ConcreteComponent implements Component
	{
		public function operation():void
		{
			trace("concreteComponent operation");
		}
	}
}      

 Decorator:

package com.mode.concrete
{
	import com.mode.interfaces.Component;
	
	public class Decorator implements Component
	{
		protected var component:Component;
		public function Decorator(comp:Component)
		{
			component = comp;
		}
		
		public function operation():void
		{
			component.operation();
		}
	}
}      

 ConcreteDecorator:

package com.mode.concrete
{
	import com.mode.interfaces.Component;
	
	public class ConcreteDecorator extends Decorator
	{
		private var additionalAttribute:String = "additional Attribute";
		public function ConcreteDecorator(comp:Component)
		{
			super(comp);
		}
		
		override public function operation():void
		{
			super.operation();
			addtionalBehavior();
		}
		private function addtionalBehavior():void
		{
			trace("Concrete decorator addtioanl behavior = " + additionalAttribute);
		}
	}
}      

 APP test:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">
	<fx:Script>
		<![CDATA[
			import com.mode.concrete.ConcreteComponent;
			import com.mode.concrete.ConcreteDecorator;
			import com.mode.concrete.Decorator;
			import com.mode.interfaces.Component;
			import com.mode.interfaces.Subject;
			import com.mode.proxy.Proxy;
			protected function button1_clickHandler(event:MouseEvent):void
			{
				var comp:Component = new ConcreteComponent();
				var decorator:Decorator = new ConcreteDecorator(comp);
				decorator.operation();
				/* output: 
				concreteComponent operation
				Concrete decorator addtioanl behavior = additional Attribute
				*/
			}
		]]>
	</fx:Script>
	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
	</fx:Declarations>
	<s:Button label="Decorator Demo" click="button1_clickHandler(event)"/>
</s:Application>      

 你會發現是我把component傳入了裝飾器中,裝飾器對component做了額外的裝飾。

(******請注意裝飾器和代理的初始化位置和方式*****)

裝飾器模式應當為所裝飾的對象提供增強功能,而代理模式對所代理對象的使用施加控制,并不提供對象本身的增強功能。

裝飾器模式關注于在一個對象上動态的添加方法,然而代理模式關注于控制對對象的通路

繼續閱讀