Design Patterns Flashcards
Singleton
O padrão Singleton garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global a essa instância. Em um banco financeiro, isso pode ser útil para gerenciar recursos compartilhados, como uma conexão de banco de dados ou um serviço de log.
public class DatabaseConnection { private static DatabaseConnection _instance; private DatabaseConnection() { } public static DatabaseConnection Instance { get { if (_instance == null) { _instance = new DatabaseConnection(); } return _instance; } } public void Connect() { // Lógica para conectar ao banco de dados } } // Uso var dbConnection = DatabaseConnection.Instance; dbConnection.Connect();
Factory Method
O Factory Method é um padrão de criação que define uma interface para criar um objeto, mas permite que as subclasses alterem o tipo de objetos que serão criados. Em um banco financeiro, isso pode ser útil para criar diferentes tipos de contas bancárias (conta corrente, poupança, etc.).
public abstract class Account { public abstract void Deposit(decimal amount); } public class SavingsAccount : Account { public override void Deposit(decimal amount) { // Lógica para depósito em conta poupança } } public class CheckingAccount : Account { public override void Deposit(decimal amount) { // Lógica para depósito em conta corrente } } public abstract class AccountFactory { public abstract Account CreateAccount(); } public class SavingsAccountFactory : AccountFactory { public override Account CreateAccount() { return new SavingsAccount(); } } public class CheckingAccountFactory : AccountFactory { public override Account CreateAccount() { return new CheckingAccount(); } } // Uso AccountFactory factory = new SavingsAccountFactory(); Account account = factory.CreateAccount(); account.Deposit(1000);
Observer
O padrão Observer permite que um objeto notifique outros objetos sobre mudanças em seu estado. Em um banco financeiro, isso pode ser útil para notificar clientes sobre mudanças em suas contas, como transações ou saldos.
public interface IObserver { void Update(string message); } public class Customer : IObserver { public void Update(string message) { Console.WriteLine($"Notificação recebida: {message}"); } } public class Account { private List<IObserver> _observers = new List<IObserver>(); public void Attach(IObserver observer) { _observers.Add(observer); } public void Detach(IObserver observer) { _observers.Remove(observer); } public void Notify(string message) { foreach (var observer in _observers) { observer.Update(message); } } public void Deposit(decimal amount) { // Lógica para depósito Notify($"Depósito de {amount} realizado."); } } // Uso var account = new Account(); var customer = new Customer(); account.Attach(customer); account.Deposit(1000);
Strategy
O padrão Strategy permite que você defina uma família de algoritmos, encapsule cada um deles e os torne intercambiáveis. Em um banco financeiro, isso pode ser útil para implementar diferentes estratégias de cálculo de juros ou taxas.
public interface IInterestStrategy { decimal CalculateInterest(decimal balance); } public class SavingsInterestStrategy : IInterestStrategy { public decimal CalculateInterest(decimal balance) { return balance * 0.02m; // 2% de juros } } public class CheckingInterestStrategy : IInterestStrategy { public decimal CalculateInterest(decimal balance) { return balance * 0.01m; // 1% de juros } } public class Account { private IInterestStrategy _interestStrategy; public Account(IInterestStrategy interestStrategy) { _interestStrategy = interestStrategy; } public void SetInterestStrategy(IInterestStrategy interestStrategy) { _interestStrategy = interestStrategy; } public decimal CalculateInterest(decimal balance) { return _interestStrategy.CalculateInterest(balance); } } // Uso var account = new Account(new SavingsInterestStrategy()); decimal interest = account.CalculateInterest(1000); Console.WriteLine($"Juros calculados: {interest}");
Decorator
O padrão Decorator permite adicionar comportamentos a objetos individualmente, de forma dinâmica, sem afetar o comportamento de outros objetos da mesma classe. Em um banco financeiro, isso pode ser útil para adicionar funcionalidades extras a contas, como seguros ou benefícios.
public abstract class Account { public abstract decimal GetBalance(); } public class BasicAccount : Account { private decimal _balance; public BasicAccount(decimal balance) { _balance = balance; } public override decimal GetBalance() { return _balance; } } public abstract class AccountDecorator : Account { protected Account _account; public AccountDecorator(Account account) { _account = account; } public override decimal GetBalance() { return _account.GetBalance(); } } public class InsuranceDecorator : AccountDecorator { public InsuranceDecorator(Account account) : base(account) { } public override decimal GetBalance() { return base.GetBalance() - 50; // Custo do seguro } } // Uso Account account = new BasicAccount(1000); account = new InsuranceDecorator(account); Console.WriteLine($"Saldo com seguro: {account.GetBalance()}");
Command
O padrão Command encapsula uma solicitação como um objeto, permitindo que você parametrize clientes com diferentes solicitações, enfileire ou registre solicitações e suporte operações que podem ser desfeitas. Em um banco financeiro, isso pode ser útil para implementar transações que podem ser desfeitas (rollback).
public interface ICommand { void Execute(); void Undo(); } public class DepositCommand : ICommand { private Account _account; private decimal _amount; public DepositCommand(Account account, decimal amount) { _account = account; _amount = amount; } public void Execute() { _account.Deposit(_amount); } public void Undo() { _account.Withdraw(_amount); } } public class Account { public decimal Balance { get; private set; } public void Deposit(decimal amount) { Balance += amount; } public void Withdraw(decimal amount) { Balance -= amount; } } // Uso var account = new Account(); var depositCommand = new DepositCommand(account, 1000); depositCommand.Execute(); Console.WriteLine($"Saldo após depósito: {account.Balance}"); depositCommand.Undo(); Console.WriteLine($"Saldo após desfazer depósito: {account.Balance}");
Facade
O padrão Facade fornece uma interface simplificada para um conjunto de interfaces em um subsistema. Em um banco financeiro, isso pode ser útil para fornecer uma interface simples para operações complexas, como abertura de contas, transferências, etc.
public class AccountService { public void CreateAccount(string accountType) { // Lógica para criar uma conta } } public class TransactionService { public void Transfer(decimal amount, string fromAccount, string toAccount) { // Lógica para transferência } } public class BankingFacade { private AccountService _accountService; private TransactionService _transactionService; public BankingFacade() { _accountService = new AccountService(); _transactionService = new TransactionService(); } public void OpenAccount(string accountType) { _accountService.CreateAccount(accountType); } public void TransferMoney(decimal amount, string fromAccount, string toAccount) { _transactionService.Transfer(amount, fromAccount, toAccount); } } // Uso var bankingFacade = new BankingFacade(); bankingFacade.OpenAccount("Savings"); bankingFacade.TransferMoney(1000, "12345", "67890");
Chain of Responsibility
O padrão Chain of Responsibility permite que você crie uma cadeia de objetos para processar uma solicitação. Cada objeto na cadeia decide se processa a solicitação ou a passa para o próximo objeto. Em um banco financeiro, isso pode ser útil para aprovação de empréstimos ou validação de transações.
public abstract class Approver { protected Approver _nextApprover; public void SetNextApprover(Approver nextApprover) { _nextApprover = nextApprover; } public abstract void ProcessLoanRequest(decimal amount); } public class Manager : Approver { public override void ProcessLoanRequest(decimal amount) { if (amount <= 10000) { Console.WriteLine("Empréstimo aprovado pelo Gerente."); } else if (_nextApprover != null) { _nextApprover.ProcessLoanRequest(amount); } } } public class Director : Approver { public override void ProcessLoanRequest(decimal amount) { if (amount <= 50000) { Console.WriteLine("Empréstimo aprovado pelo Diretor."); } else if (_nextApprover != null) { _nextApprover.ProcessLoanRequest(amount); } } } public class CEO : Approver { public override void ProcessLoanRequest(decimal amount) { Console.WriteLine("Empréstimo aprovado pelo CEO."); } } // Uso var manager = new Manager(); var director = new Director(); var ceo = new CEO(); manager.SetNextApprover(director); director.SetNextApprover(ceo); manager.ProcessLoanRequest(15000); // Aprovado pelo Diretor manager.ProcessLoanRequest(75000); // Aprovado pelo CEO
Template Method
O padrão Template Method define o esqueleto de um algoritmo em uma operação, adiando alguns passos para as subclasses. Em um banco financeiro, isso pode ser útil para implementar processos padronizados, como abertura de contas ou cálculo de taxas.
public abstract class AccountOpeningProcess { public void OpenAccount() { VerifyIdentity(); ValidateDocuments(); CreateAccount(); NotifyCustomer(); } protected abstract void VerifyIdentity(); protected abstract void ValidateDocuments(); private void CreateAccount() { Console.WriteLine("Conta criada com sucesso."); } private void NotifyCustomer() { Console.WriteLine("Cliente notificado sobre a abertura da conta."); } } public class SavingsAccountOpening : AccountOpeningProcess { protected override void VerifyIdentity() { Console.WriteLine("Verificando identidade para conta poupança."); } protected override void ValidateDocuments() { Console.WriteLine("Validando documentos para conta poupança."); } } public class CheckingAccountOpening : AccountOpeningProcess { protected override void VerifyIdentity() { Console.WriteLine("Verificando identidade para conta corrente."); } protected override void ValidateDocuments() { Console.WriteLine("Validando documentos para conta corrente."); } } // Uso AccountOpeningProcess savingsProcess = new SavingsAccountOpening(); savingsProcess.OpenAccount(); AccountOpeningProcess checkingProcess = new CheckingAccountOpening(); checkingProcess.OpenAccount();
State
O padrão State permite que um objeto altere seu comportamento quando seu estado interno muda. Em um banco financeiro, isso pode ser útil para gerenciar o estado de uma conta (ativa, bloqueada, encerrada) e definir comportamentos específicos para cada estado.
public abstract class AccountState { public abstract void Deposit(decimal amount, Account account); public abstract void Withdraw(decimal amount, Account account); } public class ActiveState : AccountState { public override void Deposit(decimal amount, Account account) { account.Balance += amount; Console.WriteLine($"Depósito de {amount} realizado. Novo saldo: {account.Balance}"); } public override void Withdraw(decimal amount, Account account) { if (account.Balance >= amount) { account.Balance -= amount; Console.WriteLine($"Saque de {amount} realizado. Novo saldo: {account.Balance}"); } else { Console.WriteLine("Saldo insuficiente."); } } } public class BlockedState : AccountState { public override void Deposit(decimal amount, Account account) { Console.WriteLine("Conta bloqueada. Depósito não permitido."); } public override void Withdraw(decimal amount, Account account) { Console.WriteLine("Conta bloqueada. Saque não permitido."); } } public class Account { public decimal Balance { get; set; } public AccountState State { get; set; } public Account() { State = new ActiveState(); // Estado inicial } public void Deposit(decimal amount) { State.Deposit(amount, this); } public void Withdraw(decimal amount) { State.Withdraw(amount, this); } public void Block() { State = new BlockedState(); Console.WriteLine("Conta bloqueada."); } public void Unblock() { State = new ActiveState(); Console.WriteLine("Conta desbloqueada."); } } // Uso var account = new Account(); account.Deposit(1000); account.Withdraw(500); account.Block(); account.Deposit(200); // Não permitido account.Withdraw(100); // Não permitido account.Unblock(); account.Deposit(200); // Permitido novamente
Proxy
O padrão Proxy fornece um substituto ou um espaço reservado para outro objeto para controlar o acesso a ele. Em um banco financeiro, isso pode ser útil para controlar o acesso a operações sensíveis, como transferências ou consultas de saldo.
public interface IBankAccount { void Deposit(decimal amount); void Withdraw(decimal amount); decimal GetBalance(); } public class RealBankAccount : IBankAccount { private decimal _balance; public void Deposit(decimal amount) { _balance += amount; Console.WriteLine($"Depósito de {amount} realizado. Novo saldo: {_balance}"); } public void Withdraw(decimal amount) { if (_balance >= amount) { _balance -= amount; Console.WriteLine($"Saque de {amount} realizado. Novo saldo: {_balance}"); } else { Console.WriteLine("Saldo insuficiente."); } } public decimal GetBalance() { return _balance; } } public class BankAccountProxy : IBankAccount { private RealBankAccount _realAccount; private string _userRole; public BankAccountProxy(string userRole) { _userRole = userRole; } public void Deposit(decimal amount) { if (_userRole == "Admin") { if (_realAccount == null) { _realAccount = new RealBankAccount(); } _realAccount.Deposit(amount); } else { Console.WriteLine("Acesso negado. Somente administradores podem depositar."); } } public void Withdraw(decimal amount) { if (_userRole == "Admin") { if (_realAccount == null) { _realAccount = new RealBankAccount(); } _realAccount.Withdraw(amount); } else { Console.WriteLine("Acesso negado. Somente administradores podem sacar."); } } public decimal GetBalance() { if (_realAccount == null) { _realAccount = new RealBankAccount(); } return _realAccount.GetBalance(); } } // Uso IBankAccount account = new BankAccountProxy("User"); account.Deposit(1000); // Acesso negado account = new BankAccountProxy("Admin"); account.Deposit(1000); // Permitido
Memento
O padrão Memento permite capturar e externalizar o estado interno de um objeto sem violar o encapsulamento, para que o objeto possa ser restaurado para esse estado posteriormente. Em um banco financeiro, isso pode ser útil para implementar funcionalidades de “desfazer” em transações.
public class BankAccountMemento { public decimal Balance { get; } public BankAccountMemento(decimal balance) { Balance = balance; } } public class BankAccount { private decimal _balance; public BankAccount(decimal balance) { _balance = balance; } public void Deposit(decimal amount) { _balance += amount; Console.WriteLine($"Depósito de {amount} realizado. Novo saldo: {_balance}"); } public void Withdraw(decimal amount) { if (_balance >= amount) { _balance -= amount; Console.WriteLine($"Saque de {amount} realizado. Novo saldo: {_balance}"); } else { Console.WriteLine("Saldo insuficiente."); } } public BankAccountMemento Save() { return new BankAccountMemento(_balance); } public void Restore(BankAccountMemento memento) { _balance = memento.Balance; Console.WriteLine($"Conta restaurada para o saldo: {_balance}"); } } // Uso var account = new BankAccount(1000); var memento = account.Save(); // Salva o estado atual account.Deposit(500); account.Withdraw(200); account.Restore(memento); // Restaura para o estado salvo
Adapter
O padrão Adapter é um padrão estrutural que permite que classes com interfaces incompatíveis trabalhem juntas. Ele atua como uma ponte entre duas interfaces, convertendo a interface de uma classe em outra interface esperada pelo cliente. Em um contexto de banco financeiro, o Adapter pode ser útil para integrar sistemas legados, APIs de terceiros ou serviços externos que possuem interfaces diferentes das esperadas pela aplicação.
Mediator
O padrão Mediator é um padrão comportamental que promove o baixo acoplamento entre objetos ao centralizar a comunicação entre eles em um único objeto, chamado de Mediator. Em vez de os objetos se comunicarem diretamente entre si, eles se comunicam através do Mediator, que coordena as interações. Isso é especialmente útil em sistemas complexos, como um banco financeiro, onde vários componentes precisam interagir de forma coordenada.