Наследование прототипов
Шаблон фабрика(фабричный метод) создает объекты в зависимости от контекста.
Помимо создания нужно унаследовать как прототип фабрики, так и прототип используемого конструктора. Как это грамотно реализовать? Код: define(['TankModel', 'ShipModel'], function (Tank, Ship) { // Factory GameModel function GameModel() {} // общие методы, которые наследуются всеми GameModel.prototype.getType = function () { console.log('this getType'); }; // фабричный метод // type - тип конструктора // params - данные для конструктора GameModel.factory = function (type, params) { var object; // вывести ошибку, если конструктор // для запрошенного типа отсутствует if (typeof GameModel[type] !== 'function') { throw { name: 'Error', message: type + ' не существует' } } // тут нужно унаследовать содержимое фабричного прототипа // делать это каждый раз при использовании одних и тех же конструкторов не нужно if (typeof GameModel[type].prototype.getType !== 'function') { GameModel[type].prototype = new GameModel(); } // тут возвращается объект от конструктора [type] object = new GameModel[type](); // работа с готовым объектом: // это метод конструктора object.initialize(params); // это метод фабрики object.getType(); return object; }; // делает танки GameModel.tank = Tank; // делает корабли GameModel.ship = Ship; return GameModel; }); Создание объекта: var tank = GameModel.factory('tank'); var ship = GameModel.factory('ship'); Эта фабрика не работает. Фабричные методы затираются при вызове конструктора |
Скопировал фабричные (общие) методы в свойство объекта (жду критики):
define(['TankModel', 'ShipModel'], function (Tank, Ship) { // Factory GameModel function GameModel() {} // общие методы, которые наследуются всеми GameModel.prototype.getType = function () { console.log('this getType'); }; // фабричный метод // type - тип конструктора // params - данные для конструктора GameModel.factory = function (type, params) { var object; // вывести ошибку, если конструктор // для запрошенного типа отсутствует if (typeof GameModel[type] !== 'function') { throw { name: 'Error', message: type + ' не существует' } } // тут возвращается объект от конструктора. // В качестве аргумента идет прототип объект, // который сохраняется в свойство объекта object = new GameModel[type](GameModel.prototype); // работа с готовым объектом: // это метод конструктора object.initialize(params); // это метод фабрики // все методы фабрики скопированы // при инициализации объекта // и доступны как object.gameModel['метод']() object.gameModel.getType(); return object; }; // делает танки GameModel.tank = Tank; // делает корабли GameModel.ship = Ship; return GameModel; }); не думаю что это лучшее решение и это уже не наследование, а копирование. А значит требует ресурсы памяти |
Не очень удачно по моему.
object = new GameModel[type](GameModel.prototype); object.initialize(params); Как то странно подмешиваемые методы передавать как параметр конструктору, а инициализацию дергать потом отдельно. По крайней мере здесь причин для этого я не вижу. Вроде вот так как то по привычнее будет. define(['TankModel', 'ShipModel'], function (Tank, Ship) { function GameModel( type, params){ //Проверка на наличие конструктора if (typeof GameModel[type] !== 'function') { throw { name: 'Error', message: type + ' не существует' } } var instance=new GameModel[type](params); //если нужно то можно подмешать методы фабрики instance.getType=GameModel.prototype.getType; return instance; } //Перечислим продукты которая может создавать фабрика GameModel.Ship=Ship; GameModel.Tank=Tank; //методы которые можно подмешивать GameMode.prototype.getType=function(){ //бла бла } }); Или может быть даже так Добавим подмешиваемые методы сразу в прототип. define(['TankModel', 'ShipModel'], function (Tank, Ship) { function GameModel( type, params){ //Проверка на наличие конструктора if (typeof GameModel[type] !== 'function') { throw { name: 'Error', message: type + ' не существует' } } return new GameModel[type](params); } //метод для добавления новых продуктов к фабрике GameModel.add=function(name,obj){ //примеси obj.prototype.getType=GameModel.prototype.getType; GameModel[name]=obj; } //Перечислим продукты которая может создавать фабрика GameModel.add('Ship',Ship); GameModel.add('Tank',Tank); //методы которые можно подмешивать GameModel.prototype.getType=function(){ //бла бла } }); Последний вариант это собрать все примеси в одном специализированном объекте, но так чтобы они могли работать с экземпляром. Первый приходящий на ум способ сделать это не вмешиваясь в работу конструктора, просто сохранить ссылку на экземпляр в замыкании. define(['TankModel', 'ShipModel'], function (Tank, Ship) { function GameModel( type, params){ //Проверка на наличие конструктора if (typeof GameModel[type] !== 'function') { throw { name: 'Error', message: type + ' не существует' } } var instance=new GameModel[type](params); instance.GameModel=Inclusions(instance); return instance } //набор включений которые добавляются фабрикой в экземпляр function Inclusions(obj) { return { getType:function(){ return typeof obj; } } } }); //вместо instance.GameModel=Inclusions(); //хватило бы и instance.GameModel={f1:function(){}, f2:function(){}} |
я не совсем понимаю как работает фабрика (да да пасоны я реал не понмиаю)
но как сделать цепочку прототипа обьяснить могу function Animals (){ function Cat (){} Cat.prototype = Object.create(Animals.prototype); function Rabbit (){} Rabbit.prototype = Object.create(Animals.prototype); } кот и кролик наследуют прототип свой и прототип фабрики |
DjDiablo, как раз то что нужно.
Выбрал 2-й вариант Спасибо! :thanks: |
доработал функцию add немного:
// метод для добавления новых продуктов к фабрике GameModel.add = function (name, object) { var props = GameModel.prototype , i; for (i in props) { if (props.hasOwnProperty(i)) { object.prototype[i] = props[i] } } GameModel[name] = object; }; |
к слову о красоте кода
// метод для добавления новых продуктов к фабрике GameModel.add = function (name, object) { var props = GameModel.prototype; for (var i in props) if (props.hasOwnProperty(i)) { object.prototype[i] = props[i] } GameModel[name] = object; }; |
а чем мой плох? )
|
Цитата:
|
а ну, если только в этом дело...
:D |
Часовой пояс GMT +3, время: 14:40. |