Que tal isso:
Você tem que criptografar um arquivo.
Para arquivos pequenos, você pode usar a estratégia "na memória", onde o arquivo completo é lido e mantido na memória (digamos para arquivos <1 gb)
Para arquivos grandes, você pode usar outra estratégia, onde partes do arquivo são lidas na memória e os resultados criptografados parciais são armazenados em arquivos tmp.
Essas podem ser duas estratégias diferentes para a mesma tarefa.
O código do cliente seria o mesmo:
File file = getFile();
Cipher c = CipherFactory.getCipher( file.size() );
c.performAction();
// implementations:
interface Cipher {
public void performAction();
}
class InMemoryCipherStrategy implements Cipher {
public void performAction() {
// load in byte[] ....
}
}
class SwaptToDiskCipher implements Cipher {
public void performAction() {
// swapt partial results to file.
}
}
o
Cipher c = CipherFactory.getCipher( file.size() );
Retornaria a instância de estratégia correta para a cifra.
Eu espero que isso ajude.
(Eu nem sei se Cipher é a palavra certa: P)
Cipher C =null; if (file.size() <= 2048) { C = new InMemoryCipherStrategy(); } else { c= SwaptToDiskCipher (); }
CipherFactory
pode confundir aqueles que não estão familiarizados com o padrão Strategy.Novamente, uma postagem antiga, mas ainda aparece em pesquisas, então adicionarei mais dois exemplos (o código está em C #). Eu adoro o padrão de estratégia, pois ele me salvou muitas vezes quando os gerentes de projeto dizem: "Queremos que o aplicativo faça 'X', mas 'X' ainda não está claro e pode mudar em um futuro próximo. " Este vídeo explicando o padrão de estratégia usa o StarCraft como exemplo.
Coisas que se enquadram nesta categoria:
Classificação: queremos classificar esses números, mas não sabemos se vamos usar BrickSort, BubbleSort ou alguma outra classificação
Validação: precisamos verificar os itens de acordo com "Alguma regra", mas ainda não está claro qual será essa regra e podemos pensar em novas.
Jogos: queremos que o jogador caminhe ou corra ao se mover, mas talvez no futuro ele também seja capaz de nadar, voar, se teletransportar, cavar no subsolo, etc.
Armazenando informações: Queremos que o aplicativo armazene informações no Banco de Dados, mas posteriormente pode ser necessário salvar um arquivo ou fazer um webcall
Saída: precisamos gerar X como uma string simples, mas posteriormente pode ser um CSV, XML, JSON, etc.
Exemplos
Eu tenho um projeto onde os usuários podem atribuir produtos a pessoas em um banco de dados. Esta atribuição de um produto a uma pessoa tem um status que é "Aprovado" ou "Recusado", que depende de algumas regras de negócios. Por exemplo: se um usuário atribui um produto a uma pessoa com uma certa idade, seu status deve ser recusado; Se a diferença entre dois campos no item for maior que 50, seu status será recusado etc.
Agora, no momento do desenvolvimento, essas regras de negócios ainda não estão totalmente claras e novas regras podem surgir a qualquer momento. O poder do stragety-pattern é que fiz um RuleAgent, que recebe uma lista de IRules.
No momento de atribuir um produto a uma pessoa, eu crio um RuleAgent, forneço a ele uma lista de regras (que implementam IRule) e peço para validar uma atribuição. Ele vai passar por todas as suas regras. Que, como todos implementam a mesma interface, todos possuem o
IsApproved
método e retornam falso se algum deles retornar falso.Agora, por exemplo, quando o gerente aparece de repente e diz, também precisamos recusar todas as atribuições de estagiários, ou todas as atribuições de pessoas trabalhando horas extras ... Você cria novas aulas como esta:
Você vê que não precisa continuar adicionando ou removendo instruções ou código if, apenas crie uma nova classe de regra que implemente a interface IRUle e troque-a quando necessário.
Outro ótimo exemplo: a série de vídeos de Scott Allen em http://www.asp.net/mvc/pluralsight, onde ele usa o padrão de estratégia na parte do teste de unidade do aplicativo
Ele constrói um site que possui uma página que exibe itens com base na popularidade. No entanto, "Popular" pode ser muitas coisas (a maioria das visualizações, a maioria dos assinantes, a data de criação, a maioria das atividades, a menor quantidade de comentários, etc.) e, no caso de o gerenciamento ainda não saber exatamente como fazer o pedido, pode querer experimentar diferentes pedidos em uma data posterior. Você faz uma interface (IOrderAlgorithm ou algo assim) com um método de pedido e deixa um objeto Orderer delegar o pedido para uma implementação concreta da interface IOrderAlgorithm. Você pode fazer um "CommentOrderer", "ActivityOrderer", etc ... E apenas substituí-los quando surgirem novos requisitos.
fonte
InternRule
agora, mas como estamos acionandoOvertimeRule
? Como podemos garantir que qualquer lógica chamadaOvertimeRule.IsApproved
agora também chameInternRule.IsApproved
?Notas principais:
Estratégia é um padrão de design comportamental. É usado para alternar entre famílias de algoritmos.
Este padrão contém uma interface de estratégia abstrata e muitas implementações de estratégia concretas ( algoritmos ) dessa interface.
O aplicativo usa apenas interface de estratégia . Dependendo de algum parâmetro de configuração, a estratégia concreta será marcada para a interface .
Diagrama UML da wikipedia
Um exemplo real: companhias aéreas oferecendo descontos durante alguns meses (julho-dezembro) . Você pode ter um módulo de tarifa , que decide as opções de preço dependendo do número do mês.
Dê uma olhada em um exemplo simples. Este exemplo pode ser estendido para aplicativos de varejo on-line, que oferecem descontos para itens do carrinho de compras em dias especiais / happy hours facilmente.
resultado:
Artigos úteis:
padrão de estratégia por dzone
padrão de estratégia por sourcemaking
fonte
Posso pensar em vários exemplos bastante simples:
Compressão de dados. Você pode ter uma interface ICompressor cujo único método se parece com isto:
byte [] comprimir (byte [] entrada);
Suas classes de compressão concretas podem ser coisas como RunLengthCompression, DeflateCompression, etc.
fonte
Um uso comum do padrão de estratégia é definir estratégias de classificação customizadas (em linguagens sem funções de ordem superior), por exemplo, classificar uma lista de strings por comprimento em Java, passando uma classe interna anônima (uma implementação da interface de estratégia):
De maneira semelhante, estratégias podem ser usadas para consultas nativas com bancos de dados de objetos, por exemplo, em db4o:
fonte
Eu tenho um aplicativo que sincroniza sua base de usuários a cada dia com o nosso diretório corporativo. Os usuários são elegíveis ou não com base em seu status na Universidade. A cada dia, o programa de provisionamento passa e garante que aqueles que deveriam ser elegíveis sejam provisionados no aplicativo e aqueles que não são desprovisionados (na verdade, de acordo com um algoritmo de degradação normal, mas isso não vem ao caso). No sábado, faço uma atualização mais completa que sincroniza algumas propriedades de cada usuário, além de garantir que eles tenham a elegibilidade adequada. No final do mês, faço algum processamento da fatura com base no uso naquele mês.
Eu uso um padrão de estratégia combinável para fazer essa sincronização. O programa principal basicamente escolhe uma estratégia mestre dependendo do dia da semana (sincronizar mudanças apenas / sincronizar tudo) e a época do semestre em relação ao calendário acadêmico. Se o ciclo de faturamento está terminando, ele também o compõe com uma estratégia de faturamento. Em seguida, executa a estratégia escolhida por meio de uma interface padrão.
Não sei o quão comum isso é, mas senti que era um ajuste perfeito para o padrão de estratégia.
fonte
Sei que essa é uma pergunta antiga, mas acho que tenho outro exemplo interessante que implementei recentemente.
Este é um exemplo muito prático do padrão de estratégia usado em um sistema de entrega de documentos.
Eu tinha um sistema de entrega de PDF que recebia um arquivo contendo muitos documentos e alguns metadados. Com base nos metadados, ele decidiu onde colocar o documento; digamos, dependendo dos dados, eu poderia armazenar o documento em
A
,B
ouC
sistemas de armazenamento, ou uma combinação dos três.Diferentes clientes usavam este sistema, e eles tinham diferentes requisitos de reversão / tratamento de erros em caso de erros: um queria que o sistema de entrega parasse no primeiro erro, deixasse todos os documentos já entregues em seus depósitos, mas parasse o processo e não entregasse mais nada ; outro queria retroceder
B
em caso de erros ao armazenarC
, mas deixar o que já foi entregueA
. É fácil imaginar que um terceiro ou quarto também terá necessidades diferentes.Para resolver o problema, criei uma classe de entrega básica que contém a lógica de entrega, além de métodos para reverter coisas de todos os armazenamentos. Esses métodos não são chamados diretamente pelo sistema de entrega em caso de erros. Em vez disso, a classe usa injeção de dependência para receber uma classe "Estratégia de manipulação de rollback / erro" (com base no cliente que usa o sistema), que é chamada em caso de erros, que por sua vez chama os métodos de rollback se for apropriado para essa estratégia.
A própria classe de entrega relata o que está acontecendo para a classe de estratégia (quais documentos foram entregues a quais armazenamentos e quais falhas aconteceram) e, sempre que ocorre um erro, ela pergunta à estratégia se deve continuar ou não. Se a estratégia diz "pare", a classe chama o método "cleanUp" da estratégia, que usa as informações relatadas anteriormente para decidir quais métodos de rollback chamar da classe de entrega ou simplesmente não faz nada.
Portanto, agora tenho duas estratégias diferentes: uma é a
QuitterStrategy
(que fecha no primeiro erro e não limpa nada) e a outra é aMaximizeDeliveryToAStrategy
(que tenta, tanto quanto possível, não abortar o processo e nunca reverter o material entregue ao armazenamentoA
, mas reverte coisas deB
se a entregaC
falhar).Do meu entendimento, este é um exemplo do padrão de estratégia. Se você (sim, você está lendo) acha que estou errado, comente abaixo e me avise. Estou curioso para saber o que constituiria um uso "puro" do padrão de estratégia e quais aspectos da minha implementação violam a definição. Acho que parece um pouco engraçado porque a interface de estratégia é um pouco gorda. Todos os exemplos que vi até agora usam apenas um método, mas ainda acho que isso encapsula um algoritmo (se uma parte da lógica de negócios pode ser considerada um algoritmo, o que eu acho que é).
Como a estratégia também é notificada sobre eventos durante a execução da entrega, ela também pode ser considerada um Observador , mas isso é outra história.
Com um pouco de pesquisa, parece que este é um "padrão composto" (como MVC, um padrão que usa vários padrões de design de uma maneira particular) chamado de Consultor . É um consultor sobre se a entrega deve continuar ou não, mas também é um gerenciador de erros ativo, pois pode reverter coisas quando solicitado.
De qualquer forma, este é um exemplo bastante complexo que pode fazer com que você sinta que os usos do padrão de estratégia são muito simples / bobos. Pode ser muito complexo e ainda mais aplicável quando usado junto com outros padrões.
fonte
O padrão de estratégia é o padrão mais comumente usado, especialmente para validações e algoritmos de classificação.
Deixe-me explicar com um exemplo prático simples
O código de teste para isso é
O mesmo exemplo foi tirado de http://coder2design.com/strategy-pattern/
fonte
Um bom exemplo de padrão de estratégia seria em um jogo onde podemos ter personagens diferentes e cada personagem pode ter várias armas para atacar, mas ao mesmo tempo pode usar apenas uma arma. Portanto, temos o personagem como contexto, por exemplo Rei, Comandante, Cavaleiro, Soldado e arma como estratégia onde ataque () pode ser o método / algoritmo que depende das armas utilizadas. Portanto, se as classes de armas de concreto fossem Espada, Machado, Besta, BowAndArrow etc., todas implementariam o método attack (). Estou certo de que não são necessárias mais explicações.
fonte
Usei a abordagem de estratégia em um mecanismo bastante complexo em um aplicativo que é um bom exemplo. Essencialmente, a função do motor era ir e primeiro encontrar uma lista de pessoas que tinham um widget, sua segunda função era descobrir quais eram as 10 melhores pessoas com um widget com base em um número desconhecido de parâmetros (coisas como preço, distância, negócios anteriores juntos , quantidade em estoque, opções de envio etc etc etc ...)
Essencialmente, o que fizemos foi dividir o problema em duas estratégias, a primeira sendo a recuperação de dados, pois sabíamos que tínhamos várias fontes de nossos widgets e precisávamos ser capazes de obter os dados e transformá-los em uma estrutura comum.
Então, também percebemos que tínhamos vários algoritmos, alguns eram baseados na ponderação dos parâmetros, outros eram muito estranhos e adequados e eu não poderia fazer justiça a eles sem apresentar visios e gráficos e bem, você entendeu, tínhamos muitos algoritmos para selecionando as melhores pessoas.
Nosso serviço em si era exatamente o que essencialmente definia as entradas, saídas e fazia alguma normalização dos dados, também usava um padrão de provedor para conectar os provedores de dados específicos do aplicativo e os provedores de algoritmo que usavam a estratégia. Este foi um sistema bastante eficaz.
Tivemos alguns debates se estávamos usando uma estratégia ou um padrão de modelo que nunca resolvemos.
fonte
Tem certeza de que o status de um "pedido" não é um padrão de estado? Tenho um palpite de que um pedido não será tratado de forma diferente dependendo do seu status.
Tomemos por exemplo o método Enviar no Pedido:
O melhor exemplo do padrão de estado (e outros padrões) que encontrei foi no livro " Head First Design Patterns ", que é incrível. Em segundo lugar estará a série de padrões de blog de David Cumps .
fonte
Digamos que você queira escrever um algoritmo para calcular o enésimo Xdia de um determinado mês e ano, por exemplo, a segunda segunda-feira de outubro de 2014. Você deseja usar a classe Tempo do Android
android.text.format.Time
para representar a data, mas também deseja escrever um algoritmo genérico que também pode se aplicar ajava.util.Calendar
.Isso é o que eu fiz.
Em DatetimeMath.java:
Em TimeMath.java:
Em OrdinalDayOfWeekCalculator.java, a classe com o algoritmo genérico:
Em meu aplicativo Android, eu chamaria algo como
Se eu quiser reutilizar o mesmo algoritmo para
java.util.Calendar
, eu apenas escreveria uma classe CalendarMath que implementa os três métodos em DatetimeMath e então usariafonte
fonte
Algumas semanas atrás, adicionei uma interface Java comum que foi implementada por um de nossos objetos de domínio. Este objeto de domínio foi carregado do banco de dados e a representação do banco de dados era um esquema em estrela com cerca de 10+ ramificações. Uma das consequências de ter um objeto de domínio de peso tão pesado é que tivemos que fazer outros objetos de domínio que representavam o mesmo esquema, embora menos pesado. Então, fiz os outros objetos leves implementarem a mesma interface. Dito de outra forma, tínhamos:
Originalmente, eu queria usar
CollectibleElephant
para classificarElephant
s. Rapidamente, meus colegas de equipe começaramCollectibleElephant
a executar verificações de segurança, filtrá-los à medida que eram enviados para a GUI etc.fonte
Tivemos que criar uma interface de provisionamento de terceiros para uma plataforma corporativa com um banco de dados muito complicado. O envio de dados a serem provisionados foi como uma lista de nossos tipos de dados que foram colocados em uma fila de prioridade em nosso aplicativo para que pudessem ser gravados no banco de dados na ordem correta devido às dependências.
O processo para gravar esses dados era então bastante simples, continue aparecendo no topo da fila de prioridade e, em seguida, escolha uma estratégia com base no tipo de objeto que você extrai.
fonte
Da wikipedia
No aplicativo do Windows Paint, você pode ver um padrão de estratégia em que pode escolher a forma e a cor independentemente em diferentes seções. Aqui, a forma e a cor são os algoritmos que podem ser alterados em tempo de execução.
Se você deseja desenhar um círculo com a cor vermelha, em vez de fornecer a opção 'RedCircle', eles permitem que você escolha o círculo e uma cor de sua escolha.
Sem estratégia padrão aumentará o número de classes com o produto cartesiano de forma e cor. Além disso, a interface muda para cada implementação.
fonte
Imagine um jogo de tiro com inimigos de IA, por exemplo. Você quer que eles lutem continuamente de maneiras diferentes com base no que acontece. Com o padrão de estratégia, você pode fazer um loop contínuo e alterar dinamicamente como uma ação específica ou será executada.
fonte