Показать сообщение отдельно
Старый 21.03.2013, 01:13
yasha005 вне форума Посмотреть профиль Отправить личное сообщение для yasha005 Найти все сообщения от yasha005
  № 9  
Ответить с цитированием
yasha005

Регистрация: Dec 2012
Сообщений: 100
Цитата:
Сообщение от Котяра Посмотреть сообщение
Хорошая книжка на эту тему - Рефакторинг Мартина Фаулера. Там нет привычных Gof шаблонов, но есть шаблоны рефакторинга. Т.е. пишем пишем - видим копипасты - выделяем метод.. Кодим дальше видим кучу одинаковых методов - выделяем фабрику и т.п..
Т.е. выбор шаблона по-ходу, а не изначально
Спасибо, вот это самый ценный совет. Я люблю подобного рода книжечки почитать.

Добавлено через 1 минуту
Цитата:
Сообщение от expl Посмотреть сообщение
Джошуа Кериевски «Рефакторинг с использованием шаблонов» туда же
Ктати, много где написано про визитор, но мало где про накапливающий параметр - а ведь последний чаще используется. В этой книге оно описано.

Степанов, кончено, на лекции в Яндекс, говорил, что нечего баловаться и читать всяких Кириевски. Но то Степанов и Яндекс. А нам, простым смертным эта книжка - самое то.
Спасибо, тоже не менее ценный для меня совет

Добавлено через 1 час 17 минут
Цитата:
Сообщение от expl Посмотреть сообщение
...Код в студию!

Не надо решать ещё не появившиеся проблемы
Так ведь в любом случае придётся расширять, так что задел под непоявившиеся проблемы должен быть


Что касается кода, я только черновые набросочки сделал, но это не окончательный вариант

Структура обмена данных:
Код AS3:
package server_exchange.server_socket_exchange
{
 
	public class SocketExchange
	{
		// Реализация шаблона одиночки
		private static var _instance:SocketExchange;
		// Реализация шаблона наблюдателя
		private var mySub:ISubject;
		// Парсит объекты из XML в Object
		private var parsingXMLtoObject:ParsingXMLtoObject
 
		public function SocketExchange(pvt:PrivateClass)
		{
			// Объект рассылки
			this.mySub = new ConcreteSubject();
			// Парсит объекты из XML в Object
			this.parsingXMLtoObject = new ParsingXMLtoObject();
		}
 
		public static function get Instance():SocketExchange
		{
			if (SocketExchange._instance == null)
			{
				SocketExchange._instance = new SocketExchange(new PrivateClass());
			}
			return SocketExchange._instance;
		}
 
		// Подписываемся на событие
		public function Subscribe(obserName:String,obserFunc:Function):void
		{
			this.mySub.AddObserver(obserName,obserFunc);
		}
 
		// Отписываемся от события
		public function UnSubscribe(obserName:String):void
		{
			this.mySub.RemoveObserver(obserName);
		}
 
		// Обновляет данные в ConcreteSubject.SetParam при получении новых данных с сервера
		public function UpdateData():void
		{
			this.parsingXMLtoObject.InputData = this.mySub.SetParam;
		}
 
 
 
	} // конец класса
 
} // конец пакета
 
 
class PrivateClass
{
	public function PrivateClass()
	{
	}
}
Интерфейс рассылки
Код AS3:
package server_exchange.server_socket_exchange
{
	//Subject Interface
	// Интерфейс рассылки
	internal interface ISubject
	{
		// Подписка наблюдателя
		function AddObserver(obserName:String,obserFunc:Function):void;
		// Отписка наблюдателя
		function RemoveObserver(obserName:String):void;
		// Уведомление наблюдателя
		function SetParam(obserName:String, objectParam:Object):void;
	}
}
Конкретная рассылка:
Код AS3:
package server_exchange.server_socket_exchange
{
	// Конкретная рассылка
	internal class ConcreteSubject implements ISubject
	{
		// Свойство хранения состояния как часть данного класса
		private var objectParam:Object;
		// Массив для хранения подписчиков-наблюдателей
		[ArrayElementType('Function')]
		private var observers:Array;
		// Имя объекта, кому конкретно предназначена рассылка
		private var observerName:String;
 
		function ConcreteSubject()
		{
			//trace('*|*Concrete Subject*|*');
			this.observers = new Array();
		}
 
		// Реализует процесс подписки
		public function AddObserver(obserName:String,obserFunc:Function):void
		{
			this.observers[obserName] = obserFunc;
		}
 
		// Реализует процесс удаления (прекращения) подписки
		public function RemoveObserver(obserName:String):void
		{
			this.observers[obserName] = null;
			delete this.observers[obserName];
		}
 
		// Процесс уведомлений
		private function NotifyObserver():void
		{
			for(var notify:String in this.observers)
			{
				// Применяется метод update из интерфейса Observer
				if (notify == this.observerName)
				{
					this.observers[notify](this.objectParam);
					this.observerName = null;
					this.objectParam = null;
					break;
				}
			}
		}
 
		// Устанавливает состояние
		public function SetParam(obserName:String,objectParam:Object):void
		{
			this.observerName = obserName;
			this.objectParam = objectParam;
			this.NotifyObserver();
		}
	} // Конец класса
} // Конец пакета

Окружение XML-экземпляра (или попросту, константы составляющие структуру XML содержимого)
Код AS3:
package server_exchange.server_socket_exchange
{
 
	internal class NameParsingXML
	{
 
		/*//////////////////////////////////////////////////
 
			Окружение xml-экземпляра модуля: CollocutorsList
 
		//////////////////////////////////////////////////*/
 
		// Статус ника в объекте cntxt[0].@statMember
		internal static const _addMember:String = 'addMember';
		internal static const _updateMember:String = 'updateMember';
		internal static const _removeMember:String = 'removeMember';
		// Назначение: чат, список в чате, приватное сообщение  cntxt[0].@nznchn
		internal static const _listAll:String = 'listAll' // для списка собеседников в чате: весь список
		internal static const _listSingle:String = 'listSingle' // для списка собеседников в чате: один посетитель
		//internal static const _mess:String = 'mess' // сообщение в чат
		//internal static const _private:String = 'private' // личное сообщение
		// Доставить в чат конкретной модели: указывается ник модели, либо в общий чат: указывается collective_chat
		// cntxt[0].@to
		internal static const _collocutors_list:String = 'collocutors_list'; // для отправки в общий список
		// Параметры ника в объекте: cntxt[0].paramNik
		internal static const _sex:String = 'sex';
		internal static const _tip:String = 'tip';
		internal static const _nikname:String  = 'nikname';
		// Параметры камеры
		internal static const _camStat = 'camStat';
		// Статус мембера: добавление, обновление или удаление cntxt[0].@statMember
		internal static const _statMember:String = 'statMember';
 
		/*///////////////////////////////////////////////////
 
			Окружение xml-экземпляра модуля: Chat
 
		///////////////////////////////////////////////////*/
 
		internal static const _collective_chat:String = 'collective_chat'; // для отправки в общий чат
		internal static const _listMessage:String = 'listMessage'; // список сообщений в чате
		internal static const _singleMessage:String = 'singleMessage'; // единичное сообщение в чат
		internal static const _addMessage:String = 'addMessage'; // статус добавления единичного сообщения в чат
 
 
 
		public function NameParsingXML()
		{
			// constructor code
		}
 
	}
 
}

Вот здесь я планирую заменить URLLoarer (собственную библиотечку, которую я ранее уже описывал вот в этом сообщении: http://www.flasher.ru/forum/showpost...54&postcount=5) на событие сокета DataEvent
Код AS3:
package server_exchange.server_socket_exchange
{
	import configure.ConfigURL;
	import configure.NameObjects;
	import languages.Lang;
	import lib_loader.ILibLoader;
	import lib_loader.LibDataLoader;
	import modules.Module;
	import modules.ModuleXMLConstName;
	import modules.NameModules;
	import modules.NameModulesSub;
 
	// Парсит объекты из XML в Object
	// Обновляет данные при получении новых данных с сервера
	internal class ParsingXMLtoObject
	{
		private var inputData:Function;
		private var libDataLoader:ILibLoader;
		private var module:Module
		private var lastError:String;
		private var lang:Lang;
 
		public function ParsingXMLtoObject()
		{
			// constructor code
			this.lang = Lang.Instance;
			this.libDataLoader = new LibDataLoader();
			this.module = Module.Instance;
		}
 
		// Обновляет данные в принимаемом методе при получении новых данных из ConcreteSubject.SetParam
		internal function set InputData(inputData:Function):void
		{
			this.inputData = inputData;
			this.StartDownload();
		}
 
		private function StartDownload():void
		{
			this.libDataLoader.SetParam = 
			{
				urlLoc: ConfigURL.cfgUrlXmlDataExchange ,
				functionComplitLoc: this.StartParsing ,
				functionErrorLoc: this.ErrorLoadData ,
				startLoc:true
			}
		}
 
		// При ошибке выдавать сообщение об ошибке
		private function ErrorLoadData(e:String):void
		{
			this.lastError = e;
			var TextError:Function = this.TextError;
			var obj:Object = 
			{
				textLoc:TextError() ,
				funcLngUpdLoc:TextError
			}
			this.module.InitModule = NameModules._MessageInfo + NameObjects._separator_ + NameModulesSub._error;
			this.module.SetParam(NameModules._MessageInfo  + NameObjects._separator_ + NameModulesSub._error , obj);
 
		}
 
		private function TextError():String
		{
			var string:String;
 
			string = this.lang.LngVar(ModuleXMLConstName._Could_not_load_data_from_the_server);
			string += '\n\n' + this.lastError + '\n\n';
			return string;
		}
 
		/*////////////////////////////////////////////////////////////
 
			Парсинг принимаемых данных
 
		////////////////////////////////////////////////////////////*/
 
		// Если данные успешно загрузились, парсим их и передаём в качестве объекта принятому ранее методу
		// желательно применить шаблон декоратор к объекту this.xmlDataObject
		private function StartParsing(e:*):void
		{
			// Принимаемый xml-листинг
			var xmlData:XML = XML(e);
			// Принимаемый обработанный объект xml-листинга 
			var takeObject:Object; // takeObject = { xmlDataObject , observerName };
 
			// Тест
			//trace(this.xmlData.name().localName);
			//trace(this.xmlData.localName());
			//for (var name:String in this.xmlData.name()) 
			//{ 
				//if (typeof (myObject[name]) == "string") 
				//{ 
					//trace(name+' = '+this.xmlData.name()[name]); //data
				//}
			//}
			// конец теста
 
 
			///////////////////////////////////////////////////////////////
			// Устанавливаем к какому модулю относится данный XML-листинг//
			switch(xmlData.name().localName)
			{
				case NameModules._CollocutorsList: 
					takeObject = ParsingCollocutorsList.CollocutorsList(xmlData);
					break;
				case NameModules._Chat:
					takeObject = ParsingChat.Chat(xmlData);
			}
			// конец соотношения установки модуля к данному XML-листингу//
			//////////////////////////////////////////////////////////////
 
 
			/*///////////////////////////////////////////////////////////
				Передача параметров объекту, принятых с сервера
			///////////////////////////////////////////////////////////*/
			if ((takeObject is Object) && (this.inputData is Function)) //&& (this.xmlDataObject is Object)) 
				this.inputData(takeObject.observerName, takeObject.xmlDataObject);
 
		} // Конец метода StartParsing
 
 
 
	} // Конец класса
} // Конец пакета

Парсинг сообщений чата:
Код AS3:
package server_exchange.server_socket_exchange
{
	// Парсинг XML листа списка собеседников: модуль CollocutorsList
	import configure.NameObjects;
 
	internal class ParsingChat
	{
		public function ParsingChat()
		{
 
		}
 
		internal static function Chat(xmlData:XML):Object
		{
			var xmlDataObject:Object;
			var observerName:String;
			var returnObject:Object;
			switch(String(xmlData.cntxt[0].@nznchn))
			{
				case NameParsingXML._listMessage:
					var addMessageList:Vector.<Object> = new Vector.<Object>();
					var i:int = xmlData.cntxt[0].AddMessage.length();
					while (--i > -1)
					{
							addMessageList.push( 
							{
								sex: String(xmlData.cntxt[0].AddMessage[i].@sex),
								nikname: String(xmlData.cntxt[0].AddMessage[i].@nikname),
								tip: String(xmlData.cntxt[0].AddMessage[i].@tip),
								flag:String(xmlData.cntxt[0].AddMessage[i].@flag),
								camStat: String(xmlData.cntxt[0].AddMessage[i].@camStat),
								date: new Date(String(xmlData.cntxt[0].AddMessage[i].@date)),
								message: String(xmlData.cntxt[0].AddMessage[i])
							});
					}
					if (addMessageList.length) 
					{
						xmlDataObject = {addMessageList:addMessageList}
						observerName = String(xmlData.name().localName) + NameObjects._separator_ + String(xmlData.cntxt[0].@to);
					}
					break;
				case NameParsingXML._singleMessage:
					switch(String(xmlData.cntxt[0].@statMessage))
					{
						case NameParsingXML._addMessage:
							xmlDataObject = 
							{
								addMessage:true ,
								sex: String(xmlData.cntxt[0].@sex),
								nikname: String(xmlData.cntxt[0].@nikname),
								tip: String(xmlData.cntxt[0].@tip),
								flag:String(xmlData.cntxt[0].@flag),
								camStat:String(xmlData.cntxt[0].@camStat),
								date: new Date(String(xmlData.cntxt[0].@date)),
								message: String(xmlData.cntxt[0])
							};
							break;
 
					}
					observerName = String(xmlData.name().localName) + NameObjects._separator_ + String(xmlData.cntxt[0].@to);
					break;
			}
 
			if (xmlDataObject is Object)
			{
				returnObject = { xmlDataObject:xmlDataObject , observerName:observerName };
				return returnObject;
			}
			else
			{
				return null;
			}
		}
 
 
	} // конец класса
} // конец пакета
Парсинг списка участников чата:
Код AS3:
package server_exchange.server_socket_exchange
{
	// Парсинг XML листа списка собеседников: модуль CollocutorsList
	import configure.NameObjects;
 
	internal class ParsingCollocutorsList
	{
		public function ParsingCollocutorsList()
		{
 
		}
 
		internal static function CollocutorsList(xmlData:XML):Object
		{
			var xmlDataObject:Object;
			var observerName:String;
			var returnObject:Object;
			switch(String(xmlData.cntxt[0].@nznchn))
			{
				case NameParsingXML._listAll:
					var addMemberList:Vector.<Object> = new Vector.<Object>();
					var i:int = xmlData.cntxt[0].AddMember.length();
					while (--i > -1)
					{
							addMemberList.push( 
							{
								sex: String(xmlData.cntxt[0].AddMember[i].@sex),
								nikname: String(xmlData.cntxt[0].AddMember[i].@nikname),
								tip: String(xmlData.cntxt[0].AddMember[i].@tip),
								flag:String(xmlData.cntxt[0].AddMember[i].@flag),
								camStat: String(xmlData.cntxt[0].AddMember[i].@camStat)
							});
					}
					if (addMemberList.length) 
					{
						xmlDataObject = {addMemberList:addMemberList}
						observerName = String(xmlData.name().localName) + NameObjects._separator_ + String(xmlData.cntxt[0].@to);
					}
					break;
				case NameParsingXML._listSingle:
					switch(String(xmlData.cntxt[0].@statMember))
					{
						case NameParsingXML._addMember:
							xmlDataObject = 
							{
								addMember:true ,
								sex: String(xmlData.cntxt[0].paramNik[0].@sex),
								nikname: String(xmlData.cntxt[0].paramNik[0].@nikname),
								tip: String(xmlData.cntxt[0].paramNik[0].@tip),
								flag:String(xmlData.cntxt[0].@flag)
							};
							break;
						case NameParsingXML._updateMember:
							xmlDataObject = 
							{
								updateMember:true ,
								nikname: String(xmlData.cntxt[0].paramNik[0].@nikname),
								camStat:String(xmlData.cntxt[0].paramNik[0].@camStat)
							};
							break;
						case NameParsingXML._removeMember:
							xmlDataObject = 
							{
								removeMember:true ,
								nikname: String(xmlData.cntxt[0].paramNik[0].@nikname)
							};
							break;
					}
					observerName = String(xmlData.name().localName) + NameObjects._separator_ + String(xmlData.cntxt[0].@to);
					break;
			}
 
			if (xmlDataObject is Object)
			{
				returnObject = { xmlDataObject:xmlDataObject , observerName:observerName };
				return returnObject;
			}
			else
			{
				return null;
			}
		}
 
 
	} // конец класса
} // конец пакета