![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
![]() |
|
|||||
|
[+1 16.03.13]
[+1 22.03.13] Регистрация: Dec 2012
Сообщений: 100
|
Посоветуйте, какой выбрать шаблон проектирования для реализации XMLSocket. Или может скомпоновать несколько шаблонов? Хотелось бы не просто тык пальцем в небо, а аргументированный выбор.
Вот список шаблонов, которое мне наиболее удобно применить: 1. Порождающе Фабричный метод Одиночка 2. Структурные Декоратор Адаптер Компоновщик 3. Поведенческие Наблюдатель Состояние |
|
|||||
|
Я срочно бросаю подготовку к свадьбе, жарить рыбу, выпиливать лобзиком и бегу переписывать своих сокетов....
Шаблон будет такой: структурный наблюдатель декорирует одиночку поведенческими адаптерами... А уж про отправку данных, отслеживание инициализации данных, парсинг и компоновку я вообще, оказывается ни разу не слышал..... Короче, коллега. Не забивайте себе голову шаблонами. Просто сядьте и пишите. Написанное вами автоматически подстроится к вашей задаче, после чего вы можете ее красиво обозвать по шаблону... И вовсе не исключено, что это не будет 4й вариант... |
|
|||||
|
[+4 06.05.14]
|
Цитата:
__________________
Марк Tween |
|
|||||
|
буду краток
модератор форума
Регистрация: Sep 2003
Адрес: Ближайшее Замкадье
Сообщений: 3,110
Записей в блоге: 28
|
А зачем вам, собственно, его реализовывать, если он уже реализован?
__________________
Отряд Котовскага |
|
|||||
|
2 yasha005:
Это не сарказм, а совет: "Bыкиньте подальше книгу про шаблоны и включите мозг". Они, конечно хорошие (кроме синглтона) и полезные (кроме визитора), но: - Ситуации в коде ваша книжка с 10-ком шаблонов не покроет, покроет только часть - Шаблон используют когда есть проблема, и, надо же, решение из книжки подходит. - Сначала пишут максимально просто - не напишете просто, а будете громоздить шаблон - ошибётесь с его выбором. И шаблон, опять же, пихать надо, если простое решение имеет проблемы. Архитектурная абстракция нагороженная без "разведки" простым кодом чаще всего оказывается неверной - создаёт больше проблем чем решает. Короче: Вот какие у Вас проблемы с сокетом? Чем он вам мешает, что сложно добавлять, где копипаста появляется? Не подумайте что я против шаблонов - наоборот, я использовал шаблоны на as3 массированно и с успехом. Просто "какой бы шаблон сюда впихнуть" - это верный признак, что Вы готовитесь создать себе проблемы. Возможно ересь, но иногда кажется, что использование шаблонов - это как раз отступление от ООП, применение костылей там, где оно плохо работает ![]() |
|
|||||
|
[+1 16.03.13]
[+1 22.03.13] Регистрация: Dec 2012
Сообщений: 100
|
Цитата:
И кстати, что касается книжки, у меня уже скопилась достаточно приличная коллекция собственных модификаций шаблонов - поэтому это ещё один аргумент в пользу шаблонов |
|
|||||
|
буду краток
модератор форума
Регистрация: Sep 2003
Адрес: Ближайшее Замкадье
Сообщений: 3,110
Записей в блоге: 28
|
Хорошая книжка на эту тему - Рефакторинг Мартина Фаулера. Там нет привычных Gof шаблонов, но есть шаблоны рефакторинга. Т.е. пишем пишем - видим копипасты - выделяем метод.. Кодим дальше - видим кучу одинаковых методов - выделяем фабрику и т.п..
Т.е. выбор шаблона по-ходу разработки, а не изначально.
__________________
Отряд Котовскага Последний раз редактировалось Котяра; 21.03.2013 в 12:39. |
|
|||||
|
Джошуа Кериевски «Рефакторинг с использованием шаблонов» туда же
Ктати, много где написано про визитор, но мало где про накапливающий параметр - а ведь последний чаще используется. В этой книге оно описано. Степанов, кончено, на лекции в Яндекс, говорил, что нечего баловаться и читать всяких Кириевски. Но то Степанов и Яндекс. А нам, простым смертным эта книжка - самое то. Цитата:
Давайте по-порядку: Он вообще сейчас работает? Что с ним не так конкретно? Цитата:
Если тяжело скроллить или хотите покрыть юнит-тестами - парсинг и компоновку вынесите в 2 отдельных класса. Я вот даже не знаю что посоветовать. Код в студию! Цитата:
Последний раз редактировалось expl; 21.03.2013 в 01:21. |
|
|||||
|
[+1 16.03.13]
[+1 22.03.13] Регистрация: Dec 2012
Сообщений: 100
|
Цитата:
Добавлено через 1 минуту Цитата:
Добавлено через 1 час 17 минут Так ведь в любом случае придётся расширять, так что задел под непоявившиеся проблемы должен быть Что касается кода, я только черновые набросочки сделал, но это не окончательный вариант Структура обмена данных: 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() { } } 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; } } 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 содержимого) 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 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 } // Конец класса } // Конец пакета Парсинг сообщений чата: 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; } } } // конец класса } // конец пакета 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; } } } // конец класса } // конец пакета |
![]() |
![]() |
Часовой пояс GMT +4, время: 16:35. |
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | |
| Опции просмотра | |
|
|