2013-10-09 6 views
-1

Редактировать: Удалены идеи более высокого уровня, включающие в себя специфический для проблемы и менее переносимый код.Javascript: унаследованные инкапсулированные переменные

Я реализовал свой DAL, используя DAO. Мое приложение подключается к различным базам данных (в основном по наследственным причинам). Чтобы облегчить эффективное и разумное использование соединений, я использую Singleton ConnectionBroker для управления различными подключениями, которые могут (или не могут быть) открыты. Затем этот ConnectionBroker вводится в DAO, где они могут запрашивать управление определенным объектом соединения, запрашивать новые соединения и т. Д.

С Наследование POV, я хотел бы что-то вроде:

AbstractDbConnection 
     |-- MongoDbConnection 
     |-- MsSqlConnection 
     |-- CouchDbConnection 
     |-- ... 

Где AbstractDbConnection определяет интерфейс, и реализует некоторую общую логику на основе событий.

var EventEmitter = require('events').EventEmitter; 

module.exports = function AbstractDbConnection(host, port, database, login, ...) { 
    // private 
    var state = StatesEnum.Closed; // StatesEnum = {Open: 0, Closed: 1, ..}; Object.freeze(StatesEnum); 

    // api that must be overwritten 
    this.connect = function connect() {throw new ...} 
    this.disconnect = function disconnect() {throw new ...} 
    ... <more> 
    this.getState = function() { return state; } 
} 
AbstractDbConnection.prototype.__proto__ = EventEmitter.prototype; 

А потом я реализовать интерфейс, используя драйвер-зависимый код:

var mssqldriver = require('mssqldriver'), //fictitious driver 
    AbstractDbConnection = require(__dirname + '/blah/AbstractDbConnection'); 


module.exports = function MsSqlConnection(host, port, database, login, ...) { 
    var me = this; 
    // implement using driver 
    this.connect = function connect() {...} 
    this.disconnect = function disconnect() {...} 
    ... <more> 
    driverSpecificConnection.on('driverSpecificOpenEvent', function() { 
     me.emit('open'); // relay driver-specific events into common events 
     state = StatesEnum.Open; // how ?? 
    } 
    ... 
} 
MsSqlConnection.prototype.__proto__ = new AbstractDbConnection(); 

Но ясно, что я хочу, чтобы защитить state свойство от изменения неосторожно.

+3

Вы должны продемонстрировать знание решаемой задачи, и предоставить свои попытки. И кажется, вы хотите, чтобы люди делали домашнее задание. – dezman

+0

@watson Я думаю, что природа вопроса подразумевает, что я понимаю трудность применения этой проблемы к прототипному языку. – Colin

+0

@watson Я не вижу, как это можно читать как «домашнее задание». Это законный проблемный домен, который нелегко решить из-за характера прототипического наследования. – Colin

ответ

1

Просто слушайте событие open в "абстрактном" конструкторе!

var EventEmitter = require('events').EventEmitter; 
module.exports = AbstractDbConnection; 
var StatesEnum = module.exports.StatesEnum = Object.freeze({ 
    Open: 0, Closed: 1, … 
}); 

function AbstractDbConnection(host, port, database, login, …) { 
    // private 
    var state = StatesEnum.Closed; 

    EventEmitter.call(this); 

    this.getState = function() { return state; } 
    this.on('open', function(e) { 
     state = StatesEnum.Open; 
    }); 
} 
AbstractDbConnection.prototype = Object.create(EventEmitter.prototype); 

// api that must be overwritten 
AbstractDbConnection.prototype.connect = function connect() {throw new …}; 
AbstractDbConnection.prototype.disconnect = function disconnect() {throw new …}; 

var Mssqldriver = require('mssqldriver'), //fictitious driver 
    AbstractDbConnection = require(__dirname + '/blah/AbstractDbConnection'); 
module.exports = MsSqlConnection; 

function MsSqlConnection(host, port, database, login, …) { 
    AbstractDbConnection.call(this); 

    this.driver = new Mssqldriver(…); 
    this.driver.on('driverSpecificOpenEvent', this.emit.bind(this, 'open')); 
    … 
} 
MsSqlConnection.prototype = Object.create(AbstractDbConnection.prototype); 
MsSqlConnection.prototype.connect = function connect() {…}; 
MsSqlConnection.prototype.disconnect = function disconnect() {…}; 
+0

Спасибо, Берги - это на самом деле очень умная идея.Плохой день вчера - спасибо, что был добрым :) – Colin

0

Вы можете использовать шаблон модуля для этого.

var transport_module = function() { 
var mileage = 0; // private 
return { 
    transport : function(distance) { 
    mileage += distance; 
    } 
    }; 
} 

//use it 
var car = transport_module(), 
boat = transport_module(), 
motorcycle = transport_module(); 


car.transport(10); 
boat.transport(5); 
motorcycle.transport(20); 

Переменный пробег не отображается ни одному другому коду javascript. Как частная переменная класса java/C++. Однако я бы подумал, нужна ли вам такая защита. Я использую модули много, но не для небольших объектов, таких как экземпляры классов в java/C++.

+0

Хмм, возможно, мне нужно перенести свое мышление от «малого объекта, подобного классам» tradOOP. Мое окончательное решение могло бы иметь отдельные конструкторы для ** автомобиля **, ** лодки ** и ** мотоцикла **. Возможно, это лучше всего обрабатывать фабрикой? – Colin

+0

Я думаю, что вы можете достичь того, что вы пытаетесь сделать с точки зрения логики, услуг и свойств с помощью javascript, но «формальности» C++, к примеру, трудно достичь. Мне всегда нравилось использование «const» в C++ для усиления смысла на уровне компилятора. Вы не можете получить это в javascript, но потенциал в гибкости стоит того. –

Смежные вопросы