Цитата:
Сообщение от Котяра
Хорошая книжка на эту тему - Рефакторинг Мартина Фаулера. Там нет привычных 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;
}
}
} // конец класса
} // конец пакета