introduzir
O modo Bridge separa peças abstratas de suas peças de implementação para que todas possam variar de forma independente.
texto
O modo Bridge é mais comumente usado no monitoramento de eventos. Vamos primeiro olhar para um pedaço de código:
A cópia do código é a seguinte:
addEvent (elemento, 'clique', getbeerbyId);
função getbeerbyId (e) {
var id = this.id;
asyncrequest ('get', 'beer.uri? id =' + id, function (resp) {
// Resposta de retorno de chamada.
console.log ('Cerveja solicitada:' + resp.Responsetext);
});
}
Há um problema com o código acima que o getBeerbyId deve ter um contexto de navegador a ser usado, porque ele usa isso. Se o contexto não for usado, será uma parada. Portanto, geralmente um programador pouco experiente transforma o programa na seguinte forma:
A cópia do código é a seguinte:
função getbeerbyId (id, retorno de chamada) {
// Envie a solicitação via ID e retorne os dados
asyncrequest ('get', 'beer.uri? id =' + id, function (resp) {
// Resposta de retorno de chamada
retorno de chamada (resp.Responsetext);
});
}
Mais prático, certo? Primeiro, o ID pode ser transmitido à vontade e uma função de retorno de chamada também é fornecida para funções de processamento personalizadas. Mas o que isso tem a ver com a ponte? É isso que o código a seguir vai refletir:
A cópia do código é a seguinte:
addEvent (elemento, 'clique', getbeerbyidbridge);
função getbeerbyidbridge (e) {
getBeerbyId (this.id, function (cerveja) {
console.log ('cerveja solicitada:'+cerveja);
});
}
Aqui, o getBeerbyidbridge é a ponte que definimos, usada para conectar o evento de clique abstrato e getbeerbyId e, ao mesmo tempo, passe o ID da fonte do evento e a função de chamada personalizada (console.log Output) para a função getBeerbyId como parâmetros.
Este exemplo parece um pouco simples, vamos dar outro exemplo prático mais complicado.
Fila de conexão XHR real
Queremos construir uma fila, que armazena muitas solicitações de Ajax na fila. O uso de filas é principalmente porque precisamos garantir que as solicitações unidas sejam processadas primeiro. A qualquer momento, podemos pausar solicitações, excluir solicitações, repetir solicitações e apoiar eventos de assinatura para cada solicitação.
Funções básicas básicas
Antes do início oficial, vamos definir várias funções de encapsulamento do núcleo. Primeiro, o primeiro é o encapsulamento de função de solicitações assíncronas:
A cópia do código é a seguinte:
var assíncrequest = (function () {
Função HandlereadyState (O, retorno de chamada) {
var poly = window.setInterval (
function () {
if (o && o.readyState == 4) {
Window.clearInterval (Poll);
if (retorno de chamada) {
retorno de chamada (O);
}
}
},
50
);
}
var getxhr = function () {
var http;
tentar {
http = novo xmlHttPrequest;
getxhr = function () {
devolver novo xmlHttPrequest;
};
}
Catch (e) {
var msxml = [
'Msxml2.xmlHttp.3.0',
'Msxml2.xmlHttp',
'Microsoft.xmlHttp'
];
for (var i = 0, len = msxml.length; i <len; ++ i) {
tentar {
http = new ActiveXObject (msxml [i]);
getxhr = function () {
retornar novo ActiveXObject (msxml [i]);
};
quebrar;
}
Catch (e) {}
}
}
retornar http;
};
Função de retorno (método, URI, retorno de chamada, pós -dados) {
var http = getxhr ();
http.open (método, URI, verdadeiro);
HandleReadyState (http, retorno de chamada);
http.send (PostData || null);
retornar http;
};
}) ();
A função de auto-execução encapsulada é uma função geral de solicitação de Ajax, e acredito que qualquer pessoa com o atributo que Ajax pode entendê-lo.
Em seguida, definimos um método geral para adicionar métodos (funções):
A cópia do código é a seguinte:
Function.prototype.method = function (nome, fn) {
this.prototype [nome] = fn;
devolver isso;
};
Por fim, adicione 2 métodos sobre matrizes, um para Traversal e outro para filtrar:
A cópia do código é a seguinte:
if (! Array.prototype.foreach) {
Array.method ('foreach', função (fn, thisobj) {
var scope = thisObj || janela;
for (var i = 0, len = this.length; i <len; ++ i) {
fn.call (escopo, este [i], i, isso);
}
});
}
if (! Array.prototype.Filter) {
Array.method ('filtro', função (fn, thisobj) {
var scope = thisObj || janela;
var a = [];
for (var i = 0, len = this.length; i <len; ++ i) {
if (! fn.call (escopo, este [i], eu, isso)) {
continuar;
}
a.push (este [i]);
}
retornar a;
});
}
Como alguns novos navegadores já suportam essas duas funções (ou algumas bibliotecas de classes já os suportam), devemos primeiro julgar se já forem suportados e, se já forem suportados, não serão mais processados.
Sistema de observador
Os observadores desempenham um papel importante no processo de eventos na fila e podem assinar eventos quando fila (sucesso, falha, pendente):
A cópia do código é a seguinte:
window.ded = window.ded || {};
Ded.util = ded.util || {};
Ded.util.observer = function () {
this.fns = [];
}
Ded.util.observer.prototype = {
Inscreva -se: function (fn) {
this.fns.push (fn);
},
Cancelar inscrição: function (fn) {
this.fns = this.fns.filter (
função (el) {
if (el! == fn) {
retornar el;
}
}
);
},
fogo: função (o) {
this.fns.foreach (
função (el) {
el (o);
}
);
}
};
O principal código de implementação da fila
Primeiro, você assina os principais atributos e delegados de eventos da fila:
A cópia do código é a seguinte:
Ded.queue = function () {
// contém a fila para solicitações.
this.queue = [];
// Use objeto observável em 3 estados diferentes para que você possa se inscrever em eventos a qualquer momento
this.OnComplete = new Ded.util.observer;
this.onfailure = new Ded.util.observer;
this.onflush = new Ded.util.observer;
// As propriedades principais podem ser definidas durante chamadas externas
this.retryCount = 3;
this.currentRetry = 0;
this.PaUsed = false;
this.timeout = 5000;
this.conn = {};
this.timer = {};
};
Então, através da chamada acorrentada de Ded.queue.Method, muitos métodos disponíveis são adicionados à fila:
A cópia do código é a seguinte:
Ded.queue.
Método ('Flush', function () {
// Método Flush
if (! this.queue.length> 0) {
retornar;
}
if (this.Paised) {
this.PaUsed = false;
retornar;
}
var que = this;
this.CurrentRetry ++;
var abort = function () {
that.conn.abort ();
if (that.currentRetry == that.retryCount) {
that.onfailure.fire ();
that.currentRetry = 0;
} outro {
that.flush ();
}
};
this.timer = window.setTimeout (abort, this.timeout);
Var callback = function (O) {
window.cleartimeout (that.timer);
that.currentRetry = 0;
that.queue.shift ();
that.onflush.fire (O.ResponseText);
if (that.queue.length == 0) {
that.OnComplete.fire ();
retornar;
}
// chamada recursiva para descarregar
that.flush ();
};
this.conn = asyncRequest (
this.queue [0] ['método'],
this.queue [0] ['Uri'],
ligar de volta,
this.queue [0] ['params']
);
}).
Método ('SetretryCount', função (contagem) {
this.retryCount = count;
}).
Método ('setTimeout', function (tempo) {
this.timeout = time;
}).
Método ('Adicionar', função (O) {
this.queue.push (o);
}).
método ('pausa', function () {
this.PaUsed = true;
}).
Método ('Dequeue', function () {
this.queue.pop ();
}).
Método ('Clear', function () {
this.queue = [];
});
O código parece muito e, depois de dobrar, você pode descobrir que ele está realmente definido na fila com métodos de descarga, SetretryCount, Settimeout, Adicionar, Pausa, Dequeue e Limpar.
Chamada simples
A cópia do código é a seguinte:
var q = new Ded.queue;
// Defina o número de tentativas um pouco mais alto para lidar com conexões lentas
Q.SetRetRyCount (5);
// Defina o tempo de tempo limite
q.setTimeout (1000);
// Adicione 2 solicitações.
Q.Add ({
Método: 'Get',
URI: '/path/to/file.php?ajax=True'
});
Q.Add ({
Método: 'Get',
URI: '/path/to/file.php?ajax=true&woe=me'
});
// Fila de descarga
q.flush ();
// pausa a fila e salve os restantes
q.Pause ();
// Claro.
q.clear ();
// Adicione 2 solicitações.
Q.Add ({
Método: 'Get',
URI: '/path/to/file.php?ajax=True'
});
Q.Add ({
Método: 'Get',
URI: '/path/to/file.php?ajax=true&woe=me'
});
// Exclua a última solicitação da fila.
Q.Dequeue ();
// Largue novamente
q.flush ();
Onde está a ponte?
Não há ponte no código de chamada acima, e a ponte? Dê uma olhada no exemplo completo abaixo e você descobrirá que há pontes em todos os lugares:
A cópia do código é a seguinte:
<!
"http://www.w3.org/tr/html4/strict.dtd">
<html>
<head>
<meta http-equiv = "content-type" content = "text/html; charset = utf-8">
<title> fila de conexão AJAX </ititle>
<script src = "utils.js"> </script>
<script src = "fileue.js"> </script>
<script type = "text/javascript">
addEvent (janela, 'load', function () {
// concluir.
var q = new Ded.queue;
Q.SetRetRyCount (5);
q.setTimeout (3000);
var itens = $ ('itens');
var resulta = $ ('resultados');
var fila = $ ('fila-itens');
// Salvar rastrear sua solicitação no cliente
var solicitações = [];
// Após cada solicitação de descarga, assine as etapas especiais de processamento
q.onflush.subscribe (function (dados) {
resultados.innerhtml = dados;
solicitações.shift ();
fileue.innerhtml = requests.toString ();
});
// Etapas de processamento de tempo de assinatura
q.onfailure.subscribe (function () {
resultados.innerhtml += '<span style = "cor: vermelho;"> erro de conexão! </span>';
});
// assine todas as etapas de processamento bem -sucedidas x
Q.OnComplete.SubScribe (function () {
resultados.innerhtml += '<span style = "cor: verde;"> concluído! </span>';
});
var açãodispatcher = function (elemento) {
switch (elemento) {
Case 'Flush':
q.flush ();
quebrar;
Caso 'Dequeue':
Q.Dequeue ();
solicitações.pop ();
fileue.innerhtml = requests.toString ();
quebrar;
Caso 'pausa':
q.Pause ();
quebrar;
caso 'claro':
q.clear ();
solicitações = [];
fileue.innerhtml = '';
quebrar;
}
};
var addRequest = function (request) {
var dados = request.split ('-') [1];
Q.Add ({
Método: 'Get',
URI: 'Bridge-Connection-quê.php? Ajax = true & s =' + dados, dados,
params: nulo
});
solicitações.push (dados);
fileue.innerhtml = requests.toString ();
};
addEvent (itens, 'clique', função (e) {
var e = e || Window.Event;
var src = e.Target || E.Srcelement;
tentar {
E.PreventDefault ();
}
Catch (ex) {
e.returnValue = false;
}
ActionDispatcher (src.id);
});
var adders = $ ('Adders');
addEvent (Adders, 'Click', function (e) {
var e = e || Window.Event;
var src = e.Target || E.Srcelement;
tentar {
E.PreventDefault ();
}
Catch (ex) {
e.returnValue = false;
}
addRequest (src.id);
});
});
</script>
<style type = "text/css" Media = "Screen">
Corpo
{
Fonte: 100% da Geórgia, Times, Serif;
}
H1, H2
{
peso-fonte: normal;
}
#fila-itens
{
Altura: 1.5em;
}
#add-steff
{
preenchimento: .5em;
Antecedentes: #DDD;
borda: 1px sólido #bbb;
}
#Resultados-área
{
preenchimento: .5em;
borda: 1px sólido #bbb;
}
</style>
</head>
<body id = "exemplo">
<div id = "doc">
<H1>
Solicitação de junção assíncrona </h1>
<div id = "fila-iteem">
</div>
<div id = "add-stuff">
<H2> Adicione uma nova solicitação à fila </h2>
<ul id = "Adders">
<li> <a href = "#" id = "action-01"> add "01" para fila </a> </li>
<li> <a href = "#" id = "action-02"> add "02" para fila </a> </li>
<li> <a href = "#" id = "action-03"> add "03" para fila </a> </li>
</ul>
</div>
<H2> Controle de cotação </h2>
<ul id = 'itens'>
<li> <a href = "#" id = "Flush"> Flush </a> </li>
<li> <a href = "#" id = "dequeue"> dequeue </a> </li>
<li> <a href = "#" id = "pausa"> pausa </a> </li>
<li> <a href = "#" id = "clear"> claro claro </a> </li>
</ul>
<div id = "Resultados-area">
<H2>
resultado:
</h2>
<div id = "Resultados">
</div>
</div>
</div>
</body>
</html>
Neste exemplo, você pode executar várias ações, como filas de descarga, pausar filas, excluir solicitações em filas, filas claras, etc. Ao mesmo tempo, acredito que todos também experimentaram o poder das pontes.
Resumir
As vantagens do modo Bridge também são óbvias. Vamos listar apenas algumas vantagens principais:
1. Separe as peças da interface e implementação. Uma implementação pode não estar vinculada a uma interface invariavelmente. A implementação da classe abstrata (função) pode ser configurada no tempo de execução, e um objeto pode até alterar sua implementação no tempo de execução. Ele também dissocia totalmente a abstração e a implementação, que também é propício à camada, gerando um sistema melhor estruturado.
2. Melhore a escalabilidade
3. Os detalhes da implementação são transparentes para os clientes e podem ocultar detalhes da implementação dos clientes.
Ao mesmo tempo, o modo Bridge também tem suas próprias desvantagens:
Um grande número de classes levará ao aumento dos custos de desenvolvimento e também pode reduzir o desempenho.