O padrão Bridge refere-se a padrões de projeto estrutural. Ele permite abstrair a implementação da lógica de classe movendo a lógica para uma classe abstrata separada. Parece simples, certo?

Suponha que implementemos um bot de spam que seja capaz de enviar mensagens para diferentes tipos de mensageiros.
Nós o implementamos usando um protocolo comum:
protocol User {
let token: String
let username: String
}
protocol Messenger {
var authorize(login: String, password: String)
var send(message: String, to user: User)
}
class iSeekUUser: User {
let token: String
let username: String
}
class iSeekU: Messenger {
var authorizedUser: User?
var requestSender: RequestSender?
var requestFactory: RequestFactory?
func authorize(login: String, password: String) {
authorizedUser = requestSender?.perform(requestFactory.loginRequest(login: login, password: password))
}
func send(message: String, to user: User) {
requestSender?.perform(requestFactory.messageRequest(message: message, to: user)
}
}
class SpamBot {
func start(usersList: [User]) {
let iSeekUMessenger = iSeekU()
iSeekUMessenger.authorize(login: "SpamBot", password: "SpamPassword")
for user in usersList {
iSeekUMessennger.send(message: "Hey checkout demensdeum blog! http://demensdeum.com", to: user)
}
}
}
Agora vamos imaginar o lançamento de um protocolo novo e mais rápido para envio de mensagens para o mensageiro iSekU. Para adicionar um novo protocolo, você precisará duplicar a implementação do bot iSekU, alterando apenas uma pequena parte dele. Não está claro por que fazer isso se apenas uma pequena parte da lógica da classe mudou. Com esta abordagem, o princípio DRY é violado; com o desenvolvimento do produto, a falta de flexibilidade se fará sentir através de erros e atrasos na implementação de novos recursos.
Vamos mover a lógica do protocolo para uma classe abstrata, implementando assim o padrão Bridge:
protocol User {
let token: String
let username: String
}
protocol Messenger {
var authorize(login: String, password: String)
var send(message: String, to user: User)
}
protocol MessagesSender {
func send(message: String, to user: User)
}
class iSeekUUser: User {
let token: String
let username: String
}
class iSeekUFastMessengerSender: MessagesSender {
func send(message: String, to user: User) {
requestSender?.perform(requestFactory.messageRequest(message: message, to: user)
}
}
class iSeekU: Messenger {
var authorizedUser: User?
var requestSender: RequestSender?
var requestFactory: RequestFactory?
var messagesSender: MessengerMessagesSender?
func authorize(login: String, password: String) {
authorizedUser = requestSender?.perform(requestFactory.loginRequest(login: login, password: password))
}
func send(message: String, to user: User) {
messagesSender?.send(message: message, to: user)
}
}
class SpamBot {
var messagesSender: MessagesSender?
func start(usersList: [User]) {
let iSeekUMessenger = iSeekU()
iSeekUMessenger.authorize(login: "SpamBot", password: "SpamPassword")
for user in usersList {
messagesSender.send(message: "Hey checkout demensdeum blog! http://demensdeum.com", to: user)
}
}
}
Uma das vantagens desta abordagem é, sem dúvida, a capacidade de expandir a funcionalidade da aplicação escrevendo plugins/bibliotecas que implementam lógica abstraída sem alterar o código da aplicação principal.
Qual é a diferença com o padrão Estratégia? Ambos os padrões são muito semelhantes, no entanto, Estratégia descreve *algoritmos* de comutação, enquanto Bridge permite alternar grandes partes de *qualquer lógica complexa*.
Fontes
https://refactoring.guru/ru/design-patterns/bridge
Código fonte
https://gitlab.com/demensdeum/patterns/ a>p>