|
|
|||||
Интересная задачка.
Я бы сделал так. Допустим есть две фигуры многоугольник и линия. Все данные (внутренний RAW формат) храним в классах Polygon и Line, которые наследуются от RawObject и являются обычной структурой данных class RawObject{ public var x:int; public var y:int; ... } class Line extends RawObject{ public var lineThickness:int=0; public var length:int=0; } class Polygon extends RawObject{ public var lineThickness:int=0; public var vertexCount:int=0; } class ScreenObject extends Sprite{ public function draw():void; public function getRawObject():RawObject; public function setRawObject():void; } Не нужные спрайты убирать с экрана, но данные обо всех объектах будут в памяти. Сериализатор/десериализатор должен быть отдельно от объекта, без свитча не обойтись, но разнести все по отдельным классам class Format1Serializer implements ISerializer{ public serialize(object:RawObject):XML{ var concreateSerializer:ISerializer; if(object is Line){ concreateSerializer = new Format1LineSerializer(); //Тут нужен пул сериалайзеров }else if (object is Polygon){ concreateSerializer = new Format1PolygonSerializer(); } return concreateSerializer.serialize(); } }
__________________
Сам себе репортер Последний раз редактировалось terbooter; 09.11.2012 в 23:52. |
|
|||||
Цитата:
А если сериализаторы решили в конструктор принимать объект и не хотят работать с другим - то пул применить и не получится. Цитата:
Без свитча здесь как раз очень даже обойтись с применением перегруженного метода. Но смысла нет, т.к. мы не избавимся от свитча при десериализации. Т.е. получится половина кода, работающего на сериализацию раскидано по компонентам, а половина запихана в свитч. Свитч не ушёл, так хоть для однообразия второй добавим - чтобы оно в одном месте всё было. Т.е. мы хотим отделить сериализацию от компонентов, но... ... по поводу оператора is: Эта штука подкидывает ошибок при рефакторинге - компилятор не скажет, если этот класс уже не является RawObject, можно так же огрести при выносе промежуточных подклассов. Стандартное решение здесь - это паттерн Посетитель. Но это плохое решение - паттерн слишком многословный и слишком ограничивает - шаг вправо/влево от области применения и созданные им проблемы затмевают всякий выигрыш (за всю историю один раз использовал и считаю, что можно было этого не делать) Можно сделать промежуточное решение (лучше is только тем что при рефакторинге меньше проблем подкидывает, заявить что его надо прямо использовать я не готов, но всё же): class RawObject{ public var x:int; public var y:int; ... public function get asLine():Line { return null }; public function get asPolygon():Polygon { return null }; } class Line extends RawObject{ public var lineThickness:int=0; public var length:int=0; override public function get asLine():Line { return this; }; } class Polygon extends RawObject{ public var lineThickness:int=0; public var vertexCount:int=0; override pulbic function get asPolygon():Polygon { return this; }; } Отличите от is только в том, что если класс исчезнет из иерархии этих объектов при рефакторинге, и некоторых других рефакторинговых претурбациях компилятор потыкает на места, которые было бы неплохо поправить. Только и всего. Плюс понятно по каким сущностям ходить в свитче - это просто списко полей, начинающихся на as у RawObject. С is по каким классам свитчить не так очевидно. Последний раз редактировалось expl; 09.11.2012 в 23:27. |
|
|||||
Что касается инспектора свойств, то я сделал бы так.
Каждое свойство загнать в интерфейс. Обычно бывает много одинаковых свойств, поэтому можно несколько свойств помещать в один интерфейс расширяя интерфейсы. Тут зависит от того какие будут у вас объекты. Само же свойство сделать отдельным объектом class Property{ public function Property(contextObject:RawObject){ } public var name:String; public var description:String; public function setPropertyValue(value:String){ } public function getPropertyValue():String{ } } interface IVertexCount { function getVertexCount():int; function setVertexCount(value:int):void; } class VertexCountProperty{ public function VertexCountProperty(contextObject:RawObject){ super(contextObject); name = "Число вершин"; description = "Задайте количество вершин"; } override public function setPropertyValue(value:String){ (contextObject as IVertexCount).setVertexCount(parseInt(value)); } override public function getPropertyValue():String{ (contextObject as IVertexCount).getVertexCount().toString(); } } public var properties:Array; Если выделить на экране ScreenObject, то инспектор свойств получит ссылку на этот объект, возьмет из него RawObject в котором хранятся все доступные для изменения свойства. Пробегаем массив. Строим формочку для отображения свойств. Когда юзер изменил свойство и нажал "ок", то у соответствующего свойства вызываем setPropertyValue, а у экранного объекта вызываем draw(), чтобы обновить графическое представление изменившейся модели Добавлено через 5 минут expl, я отредактировал пост. PolygonSerializer заменил на Format1PolygonSerializer. У меня мысль тут такая: Количество классов сериалайзеров = количество фигур * ко-во форматов
__________________
Сам себе репортер |
|
|||||
С точки зрения Adobe нет ничего плохого в том' что объект умеет себя сериализовать и десериализовать. Примеры из API плеера: методы toString и toJSON, интерфейс IExternalizable.
Насчет архитектуры я бы посоветовал обратить внимание на пакет spark.primitives из Flex framework. Отличная структура и расширяемость.
__________________
משיח לא בא משיח גם לא מטלפן |
|
|||||
Цитата:
P.S. Свитч, конечно, заменяется более расширяемой структурой - регистром типов. Например, в сериализаторе AMF - это регистрация типов по registerClassAlias. Было б ради чего. |
|
|||||
Можно и без switch, если сериализованный объект будет содержать qualified class name или алиас (соответственно в приложении должен быть ассоциативный массив с алиасами в качестве ключей и классами в качестве значений).
__________________
משיח לא בא משיח גם לא מטלפן |
|
|||||
Цитата:
Цитата:
Не проще ли сделать прямо в объекте нужного типа простые геттеры и сеттеры, которых нет у других типов. Сделать для всех метод getEditorPanel():EditorPanelBase А в этом методе передать себя в конструктор ConcreteEditorPanel Каждый подтип EditorPanelBase будет принимать объект конкретного типа и брать и менять нужные поля без всяких приведений. И приведений типов не надо - и структура простая. Зачем астронавтить? Цитата:
|
|
||||||
Цитата:
Да, я предлагаю метод serialize() вынести в отдельный класс. В этом же классе можно сделать desirialize(), можно и в отдельном. Я считаю это не сильно важным моментом. Главное тут, что данные объекта хранятся не в потомке спрайта. Добавлено через 1 минуту Цитата:
Добавлено через 14 минут Цитата:
Нет, не перебор. Так как мы имеем четкую и понятную сущность Property, которую можно универсально использовать в любой панели свойств. Ваш вариант предлагает рисовать для каждого случая новую панельку (Line для LinePropertyPanel и тд) Добавлено через 18 минут Цитата:
Но при этом он должен знать про класс ConcreteEditorPanel! Категорически не согласен. Не надо все валить в один бедный объект Добавлено через 36 минут Цитата:
__________________
Сам себе репортер |
|
|||||
1. Про суть:
там были замечания по поводу того что: - разделять сериализатор и десериализатор объекта по 2-м разным классам не является необходимостью - можно и на одном 2 метода держать. - is создает проблемы, есть кривенький способ решить 2. По поводу свитча разногласий нет 3. По поводу панели: Вообще, да, Ваш подход имеет право на жизнь. С одной стороны много панелек и простые компоненты, с другой - усложнённые компоненты, куча интерфейсов, но более универсальное отображение панелек. Но я бы начал с панелки на компонент Потом если объектов станет много - разбил бы её на части, а в компоненте в методе писал бы не new ConcretePanel(this), а var panel:CompositePanel = new CompositePanel(); panel.addBlock(new PositionBlock(this.position)) panel.addBlock(new ColorBlock(this.color)) return panel; 4. Цитата:
Ну а то что должен знать про панель - это критично только если код объекта библиотечный. Тогда это нехило затруднит использование объекта в другом проекте. А если нет - это даже unit-тестированию не помешает. Ну не городить же свитчи и регистры соответсвия объект-панель пока и без них неплохо. 5. Цитата:
Eсли сериализатор не хранит объект, то чистка не нужна и пул не нужен - сохраняем по сериализатору на тип объекта - больше одного на тип не потребуется. Если сериализатор хранит состояние - то можно просто после вызова serialize() почистить и опять же пул не нужен. Нет, не так: Здесь будет до 20 пулов, которые не будут создавать больше 1-го объекта (многие парсеры разных типов ведь - в один пул пихать нельзя). Т.е. пул работать будет, но здесь проще 20 полей с сериализаторами слепить вместо 20-ти пулов |
|
|||||
В целом согласен.
Принципиальное разногласие вижу в пунктах 3-4. А именно, я предлагаю механизм как выделить свойства фигур, которые может изменять пользователь. А вы предлагаете оставить это решение "на потом", а сейчас захардкодить панельки в ConcreteRawObject. Согласен, что можно и захардкодить. Но судя по описанию задачи намечается довольно сложный векторный редактор, поэтому я предложил решение с запасом
__________________
Сам себе репортер |
Часовой пояс GMT +4, время: 16:23. |
|
« Предыдущая тема | Следующая тема » |
Теги |
архитектура , паттерн , Проектирование |
|
|