ActionScript 3 (Flash/AIR): GoF デザインパターン – Mediator

とあるクラスの中に、他のクラスを入れる変数が色々あって、別のクラスでもそんな感じでお互い変数に入れ合っていて、入れ替わるたびにお互い渡し直すのは煩雑になりがちなので、それらの変数をまとめて持つクラスを一つ作って管理させるとスッキリするっていう設計です。

要はメインクラス(Mediator)を作ってメインから指示されるクラス(Colleague)は共通のインターフェースを持つか共通のスーパークラスを持ってポリモーフィズムするってことかもしれません。

ユーザーインターフェースを作成するときによくつかわれるそうです。

Facade に似ていますが、Mediator は、あるオブジェクト群の間で行われる通信を仲介します。裏方で情報を集約して指示を出す調整役と言えます。

ActionScript: Mediator.as

package jp.feb19.gof.mediator
{
	public class Mediator
	{
		public function Mediator()
		{
			
		}
		
		public function register(person:Colleague):void
		{
			
		}
		
		public function send(from:String, to:String, message:String):void
		{
			
		}
	}
}

ActionScript: Colleague.as

package jp.feb19.gof.mediator
{
	public class Colleague
	{
		private var _name:String;
		private var _chatRoom:ChatRoom;
		
		public function Colleague(name:String)
		{
			_name = name;
		}
		
		public function get name():String
		{
			return _name;
		}
		
		public function set chatRoom(value:ChatRoom):void
		{
			_chatRoom = value;
		}
		
		public function get chatRoom():ChatRoom
		{
			return _chatRoom;
		}
		
		public function send(to:String, message:String):void
		{
			_chatRoom.send(_name, to, message);
		}
		
		public function receive(from:String, message:String):void
		{
			trace(from + " to " + _name + ": " + message);  
		}
	}
}

ActionScript: ChatRoom.as

package jp.feb19.gof.mediator
{
	import flash.utils.Dictionary;
	public class ChatRoom extends Mediator
	{
		private var _people:Dictionary;
		
		public function ChatRoom()
		{
			_people = new Dictionary();
			
			super();
			
		}
		
		override public function register(person:Colleague):void
		{
			if (!_people[person.name])
				_people[person.name] = person;
			
			// mediator を教えとく
			person.chatRoom = this;
		}
		
		override public function send(from:String, to:String, message:String):void
		{
			var person:Colleague = _people[to];
			
			if (person != null)
				person.receive(from, message);
		}
	}
}

Colleague サブクラス

ActionScript: Staff.as

package jp.feb19.gof.mediator
{
	public class Staff extends Colleague
	{
		public function Staff(name:String)
		{
			super(name);
		}
		
		override public function receive(from:String, message:String):void
		{
			trace("to a staff");
			super.receive(from, message);
		}
	}
}

ActionScript: Member.as

package jp.feb19.gof.mediator
{
	public class Member extends Colleague
	{
		public function Member(name:String)
		{
			super(name);
		}
		
		override public function receive(from:String, message:String):void
		{
			trace("to a member");
			super.receive(from, message);
		}
	}
}

テストクラス

ActionScript: MediatorTest.as

package jp.feb19.gof.mediator
{
	import flash.display.Sprite;
	
	public class MediatorTest extends Sprite
	{
		public function MediatorTest()
		{
			super();
			
			var chatRoom:ChatRoom = new ChatRoom();
			
			var hosono		:Member = new Member("Haruomi Hosono");
			var sakamoto	:Member = new Member("Ryuichi Sakamoto");
			var takahashi	:Member = new Member("Yukihiro Takahashi");
			var matsutake	:Staff = new Staff("Hideki Matsutake");
			
			chatRoom.register(hosono);
			chatRoom.register(sakamoto);
			chatRoom.register(takahashi);
			chatRoom.register(matsutake);
			
			hosono.send("Ryuichi Sakamoto", "ああああ");
			sakamoto.send("Yukihiro Takahashi", "いいいい");
			takahashi.send("Haruomi Hosono", "うううう");
			matsutake.send("Haruomi Hosono", "ええええ");
			takahashi.send("Hideki Matsutake", "おおおお");
		}
	}
}

出力

to a member
Haruomi Hosono to Ryuichi Sakamoto: ああああ
to a member
Ryuichi Sakamoto to Yukihiro Takahashi: いいいい
to a member
Yukihiro Takahashi to Haruomi Hosono: うううう
to a member
Hideki Matsutake to Haruomi Hosono: ええええ
to a staff
Yukihiro Takahashi to Hideki Matsutake: おおおお