Está en la página 1de 113

Contenido

Patrones de diseño - Inicio


Patrones de diseño: descripción general
Patrones de diseño - Patrón de fábrica
Patrón abstracto de fábrica
Patrones de diseño - Patrón Singleton
Patrones de diseño - Patrón de constructor
Patrones de diseño - Patrón prototipo
Patrones de diseño - Patrón de adaptador
Patrones de diseño - Patrón de puente
Patrones de diseño - Patrón de filtro
Patrones de diseño - Patrón compuesto
Patrones de diseño - Patrón de decorador
Patrones de diseño - Patrón de fachada
Patrones de diseño - Patrón Flyweight
Patrones de diseño - Patrón proxy
Patrón de cadena de responsabilidad
Patrones de diseño - Patrón de comando
Patrones de diseño - Patrón de intérprete
Patrones de diseño - Patrón iterador
Patrones de diseño - Patrón de mediador
Patrones de diseño - Patrón de recuerdo
Patrones de diseño - Patrón de observador
Patrones de diseño - Patrón de estado
Patrones de diseño - Patrón de objeto nulo
Patrones de diseño - Patrón de estrategia
Patrones de diseño - Patrón de plantilla
Patrones de diseño - Patrón de visitante
Patrones de diseño - Patrón MVC
Patrón de delegado comercial
Patrón de entidad compuesta
Patrón de objeto de acceso a datos
Patrón de controlador frontal
Patrón de filtro interceptor
Patrón de localizador de servicio
Transferir patrón de objeto
Guía rápida de patrones de diseño
Los patrones de diseño representan las mejores prácticas utilizadas por
desarrolladores experimentados de software orientado a objetos. Los patrones
de diseño son soluciones a problemas generales que los desarrolladores de
software enfrentaron durante el desarrollo de software. Estas soluciones
fueron obtenidas por prueba y error por numerosos desarrolladores de
software durante un período de tiempo bastante sustancial.

¿Qué es la cuadrilla de cuatro (GOF)?


En 1994, cuatro autores Erich Gamma, Richard Helm, Ralph Johnson y John
Vlissides publicaron un libro titulado Patrones de diseño: elementos de
software orientado a objetos reutilizables que inició el concepto de patrón
de diseño en el desarrollo de software.
Estos autores se conocen colectivamente como Gang of Four (GOF) . Según
estos autores, los patrones de diseño se basan principalmente en los
siguientes principios del diseño orientado a objetos.
 Programa para una interfaz, no una implementación
 Favorecer la composición de objetos sobre la herencia

Uso del patrón de diseño


Los patrones de diseño tienen dos usos principales en el desarrollo de
software.

Plataforma común para desarrolladores

Los patrones de diseño proporcionan una terminología estándar y son


específicos para un escenario particular. Por ejemplo, un patrón de diseño
singleton significa el uso de un solo objeto, por lo que todos los
desarrolladores que estén familiarizados con el patrón de diseño único harán
uso de un solo objeto y podrán decirse entre sí que el programa está
siguiendo un patrón singleton.

Mejores prácticas

Los patrones de diseño se han desarrollado durante un largo período de


tiempo y proporcionan las mejores soluciones a ciertos problemas que se
enfrentan durante el desarrollo de software. Aprender estos patrones ayuda a
los desarrolladores sin experiencia a aprender el diseño de software de una
manera fácil y rápida.
www.postparaprogramadores.com
/
Tipos de patrones de diseño
Según el libro de referencia de patrones de diseño Design Patterns -
Elements of Reusable Object-Oriented Software , existen 23 patrones de
diseño. Estos patrones se pueden clasificar en tres categorías: patrones de
creación, estructurales y de comportamiento. También discutiremos otra
categoría de patrones de diseño: patrones de diseño J2EE.

SN Patrón y descripción

Patrones de creación
Estos patrones de diseño proporcionan una forma de crear objetos mientras se oculta la
1 lógica de creación, en lugar de crear instancias de objetos directamente utilizando un nuevo
operador. Esto le da al programa más flexibilidad para decidir qué objetos deben crearse
para un caso de uso dado.

Patrones estructurales
Estos patrones de diseño se refieren a la composición de clases y objetos. El concepto de
2
herencia se utiliza para componer interfaces y definir formas de componer objetos para
obtener nuevas funcionalidades.

Patrones de comportamiento
3
Estos patrones de diseño se refieren específicamente a la comunicación entre objetos.

Patrones J2EE
4 4 Estos patrones de diseño están específicamente relacionados con el nivel de
presentación. Sun Java Center identifica estos patrones.

Síguenos en Instagram para que estés al tanto de los


nuevos libros de programación. Click aqui
Patrón de fábrica
El patrón de fábrica es uno de los patrones de diseño más utilizados en
Java. Este tipo de patrón de diseño viene bajo el patrón de creación, ya que
este patrón proporciona una de las mejores formas de crear un objeto.
En el patrón Factory, creamos objetos sin exponer la lógica de creación al
cliente y hacemos referencia al objeto recién creado utilizando una interfaz
común.

Implementación
Vamos a crear una interfaz Shape y clases concretas implementando
la interfaz Shape . Una clase de fábrica ShapeFactory se define como el
siguiente paso.
FactoryPatternDemo , nuestra clase de demostración
utilizará ShapeFactory para obtener un objeto Shape . Pasará información
( CIRCLE / RECTANGLE / SQUARE ) a ShapeFactory para obtener el tipo de
objeto que necesita.

Paso 1
Crea una interfaz.
Shape.java
public interface Shape {
void draw();
}

Paso 2
Crear clases concretas implementando la misma interfaz.
Rectangle.java
public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}

Square.java
public class Square implements Shape {

@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Circle.java
public class Circle implements Shape {

@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}

Paso 3
Cree una Fábrica para generar objetos de clase concreta en función de la
información dada.
ShapeFactory.java
public class ShapeFactory {

//use getShape method to get object of type shape


public Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}

Etapa 4
Use la Fábrica para obtener un objeto de clase concreta pasando información
como tipo.
FactoryPatternDemo.java
public class FactoryPatternDemo {

public static void main(String[] args) {


ShapeFactory shapeFactory = new ShapeFactory();

//get an object of Circle and call its draw method.


Shape shape1 = shapeFactory.getShape("CIRCLE");

//call draw method of Circle


shape1.draw();

//get an object of Rectangle and call its draw method.


Shape shape2 = shapeFactory.getShape("RECTANGLE");

//call draw method of Rectangle


shape2.draw();

//get an object of Square and call its draw method.


Shape shape3 = shapeFactory.getShape("SQUARE");

//call draw method of square


shape3.draw();
}
}

Paso 5
Verifique la salida.
Círculo interno :: método draw ().
Rectángulo interior :: método draw ().
Inside Square :: método draw ().
Patrón de diseño - Patrón abstracto de
fábrica
Los patrones de Abstract Factory funcionan en torno a una súper fábrica que
crea otras fábricas. Esta fábrica también se llama fábrica de fábricas. Este tipo
de patrón de diseño viene bajo el patrón de creación, ya que este patrón
proporciona una de las mejores formas de crear un objeto.
En el patrón Abstract Factory, una interfaz es responsable de crear una fábrica
de objetos relacionados sin especificar explícitamente sus clases. Cada
fábrica generada puede dar los objetos según el patrón de Fábrica.

Implementación
Vamos a crear una interfaz Shape y una clase concreta para
implementarla. Creamos una clase abstracta de fábrica AbstractFactory como
siguiente paso. Se define la clase de fábrica ShapeFactory, que extiende
AbstractFactory. Se crea una clase de creador / generador de fábrica
FactoryProducer.
AbstractFactoryPatternDemo, nuestra clase de demostración utiliza
FactoryProducer para obtener un objeto AbstractFactory. Pasará información
(CIRCLE / RECTANGLE / SQUARE para Shape) a AbstractFactory para
obtener el tipo de objeto que necesita.

Paso 1
Crear una interfaz para formas.
Shape.java
public interface Shape {
void draw();
}
Paso 2
Crear clases concretas implementando la misma interfaz.
RoundedRectangle.java
public class RoundedRectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside RoundedRectangle::draw()
method.");
}
}
RoundedSquare.java
public class RoundedSquare implements Shape {
@Override
public void draw() {
System.out.println("Inside RoundedSquare::draw()
method.");
}
}
Rectangle.java
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}

Paso 3
Cree una clase abstracta para obtener fábricas para objetos de forma normal y
redondeada.
AbstractFactory.java
public abstract class AbstractFactory {
abstract Shape getShape(String shapeType) ;
}

Etapa 4
Cree clases Factory extendiendo AbstractFactory para generar objetos de
clase concreta en base a la información dada.
ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
}else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}

RoundedShapeFactory.java
public class RoundedShapeFactory extends AbstractFactory {
@Override
public Shape getShape(String shapeType){
if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new RoundedRectangle();
}else if(shapeType.equalsIgnoreCase("SQUARE")){
return new RoundedSquare();
}
return null;
}
}

Paso 5
Cree una clase de generador / productor de Fábrica para obtener fábricas
pasando una información como Forma
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getFactory(boolean rounded){
if(rounded){
return new RoundedShapeFactory();
}else{
return new ShapeFactory();
}
}
}

Paso 6
Use FactoryProducer para obtener AbstractFactory para obtener fábricas de
clases concretas pasando una información como type.
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//get rounded shape factory
AbstractFactory shapeFactory =
FactoryProducer.getFactory(false);
//get an object of Shape Rounded Rectangle
Shape shape1 = shapeFactory.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape1.draw();
//get an object of Shape Rounded Square
Shape shape2 = shapeFactory.getShape("SQUARE");
//call draw method of Shape Square
shape2.draw();
//get rounded shape factory
AbstractFactory shapeFactory1 =
FactoryProducer.getFactory(true);
//get an object of Shape Rectangle
Shape shape3 = shapeFactory1.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape3.draw();
//get an object of Shape Square
Shape shape4 = shapeFactory1.getShape("SQUARE");
//call draw method of Shape Square
shape4.draw();

}
}

Paso 7
Verifique la salida.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside RoundedRectangle::draw() method.
Inside RoundedSquare::draw() method.
Patrón Singleton
El patrón Singleton es uno de los patrones de diseño más simples en
Java. Este tipo de patrón de diseño viene bajo el patrón de creación, ya que
este patrón proporciona una de las mejores formas de crear un objeto.
Este patrón involucra una sola clase que es responsable de crear su propio
objeto mientras se asegura de que solo se cree un solo objeto. Esta clase
proporciona una forma de acceder a su único objeto al que se puede acceder
directamente sin necesidad de instanciar el objeto de la clase.

Implementación
Vamos a crear una clase SingleObject . La clase SingleObject tiene su
constructor como privado y tiene una instancia estática de sí mismo.
La clase SingleObject proporciona un método estático para llevar su instancia
estática al mundo exterior. SingletonPatternDemo , nuestra clase de
demostración utilizará la clase SingleObject para obtener
un objeto SingleObject .
Paso 1
Crea una clase Singleton.
SingleObject.java
public class SingleObject {

//create an object of SingleObject


private static SingleObject instance = new SingleObject();

//make the constructor private so that this class cannot


be
//instantiated
private SingleObject(){}

//Get the only object available


public static SingleObject getInstance(){
return instance;
}

public void showMessage(){


System.out.println("Hello World!");
}
}

Paso 2
Obtenga el único objeto de la clase singleton.
SingletonPatternDemo.java
public class SingletonPatternDemo {
public static void main(String[] args) {

//illegal construct
//Compile Time Error: The constructor SingleObject() is
not visible
//SingleObject object = new SingleObject();

//Get the only object available


SingleObject object = SingleObject.getInstance();

//show the message


object.showMessage();
}
}

Paso 3
Verifique la salida.
Hola Mundo!
Patrón de constructor
El patrón de construcción construye un objeto complejo usando objetos
simples y usando un enfoque paso a paso. Este tipo de patrón de diseño viene
bajo el patrón de creación, ya que este patrón proporciona una de las mejores
formas de crear un objeto.
Una clase Builder construye el objeto final paso a paso. Este constructor es
independiente de otros objetos.

Implementación
Hemos considerado un caso de negocios de restaurante de comida rápida
donde una comida típica podría ser una hamburguesa y una bebida fría. La
hamburguesa puede ser una hamburguesa vegetariana o una hamburguesa
de pollo y estará empacada en una envoltura. La bebida fría puede ser una
coca cola o una pepsi y se envasará en una botella.
Vamos a crear un artículo de interfaz que representa alimentos como
hamburguesas y bebidas frías y clases concretas de aplicación
del artículo interfaz y un embalaje interfaz que representa el envasado de
alimentos y clases concretas de aplicación del Embalaje interfaz como
hamburguesa sería embalado en la envoltura y el frío la bebida se empacaría
como una botella.
Luego creamos una clase Meal con ArrayList of Item y un MealBuilder para
construir diferentes tipos
de objetos Meal combinando Item . BuilderPatternDemo , nuestra clase de
demostración utilizará MealBuilder para crear una comida .

Paso 1
Cree un elemento de interfaz que represente el alimento y el embalaje.
Item.java
public interface Item {
public String name();
public Packing packing();
public float price();
}

Embalaje.java
public interface Packing {
public String pack();
}

Paso 2
Cree clases concreadas implementando la interfaz de embalaje.
Wrapper.java
public class Wrapper implements Packing {
@Override
public String pack() {
return "Wrapper";
}
}

Bottle.java
public class Bottle implements Packing {

@Override
public String pack() {
return "Bottle";
}
}

Paso 3
Cree clases abstractas que implementen la interfaz del elemento
proporcionando funcionalidades predeterminadas.
Burger.java
public abstract class Burger implements Item {

@Override
public Packing packing() {
return new Wrapper();
}

@Override
public abstract float price();
}

ColdDrink.java
public abstract class ColdDrink implements Item {

@Override
public Packing packing() {
return new Bottle();
}

@Override
public abstract float price();
}

Etapa 4
Crear clases concretas que extiendan las clases Burger y ColdDrink
VegBurger.java
public class VegBurger extends Burger {

@Override
public float price() {
return 25.0f;
}

@Override
public String name() {
return "Veg Burger";
}
}
ChickenBurger.java
public class ChickenBurger extends Burger {

@Override
public float price() {
return 50.5f;
}

@Override
public String name() {
return "Chicken Burger";
}
}
Coca-Cola.
public class Coke extends ColdDrink {

@Override
public float price() {
return 30.0f;
}

@Override
public String name() {
return "Coke";
}
}
Pepsi.java
public class Pepsi extends ColdDrink {

@Override
public float price() {
return 35.0f;
}

@Override
public String name() {
return "Pepsi";
}
}

Paso 5
Cree una clase de comida que tenga objetos Item definidos anteriormente.
Meal.java
import java.util.ArrayList;
import java.util.List;

public class Meal {


private List<Item> items = new ArrayList<Item>();

public void addItem(Item item){


items.add(item);
}

public float getCost(){


float cost = 0.0f;
for (Item item : items) {
cost += item.price();
}
return cost;
}

public void showItems(){


for (Item item : items) {
System.out.print("Item : "+item.name());
System.out.print(", Packing :
"+item.packing().pack());
System.out.println(", Price : "+item.price());
}
}
}

Paso 6
Cree una clase MealBuilder, la clase de generador real responsable de crear
objetos Meal.
MealBuilder.java
public class MealBuilder {

public Meal prepareVegMeal (){


Meal meal = new Meal();
meal.addItem(new VegBurger());
meal.addItem(new Coke());
return meal;
}
public Meal prepareNonVegMeal (){
Meal meal = new Meal();
meal.addItem(new ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}

Paso 7
BuiderPatternDemo usa MealBuider para demostrar el patrón del generador.
BuilderPatternDemo.java
public class BuilderPatternDemo {
public static void main(String[] args) {
MealBuilder mealBuilder = new MealBuilder();

Meal vegMeal = mealBuilder.prepareVegMeal();


System.out.println("Veg Meal");
vegMeal.showItems();
System.out.println("Total Cost: " +vegMeal.getCost());

Meal nonVegMeal = mealBuilder.prepareNonVegMeal();


System.out.println("\n\nNon-Veg Meal");
nonVegMeal.showItems();
System.out.println("Total Cost: "
+nonVegMeal.getCost());
}
}

Paso 8
Verifique la salida.
Comida Vegetariana
Artículo: hamburguesa vegetariana, embalaje: envoltura,
precio: 25.0
Artículo: Coca-Cola, Embalaje: Botella, Precio: 30.0
Costo total: 55.0

Comida no vegetariana
Artículo: hamburguesa de pollo, embalaje: envoltura, precio:
50.5
Artículo: Pepsi, Embalaje: Botella, Precio: 35.0
Costo total: 85.5
Patrón prototipo
El patrón prototipo se refiere a la creación de objetos duplicados mientras se
tiene en cuenta el rendimiento. Este tipo de patrón de diseño viene bajo el
patrón de creación, ya que este patrón proporciona una de las mejores formas
de crear un objeto.
Este patrón implica la implementación de una interfaz prototipo que le indica
que cree un clon del objeto actual. Este patrón se utiliza cuando la creación de
objetos directamente es costosa. Por ejemplo, se debe crear un objeto
después de una operación costosa de la base de datos. Podemos almacenar
en caché el objeto, devolver su clon en la próxima solicitud y actualizar la base
de datos cuando sea necesario, reduciendo así las llamadas a la base de
datos.

Implementación
Vamos a crear una clase abstracta Forma y clases concretas que extiendan
la clase Forma . Una clase ShapeCache se define como el siguiente paso que
almacena objetos de forma en una tabla hash y devuelve su clon cuando se le
solicita.
PrototypPatternDemo , nuestra clase de demostración utilizará
la clase ShapeCache para obtener un objeto Shape .

Paso 1
Cree una clase abstracta implementando la interfaz Clonable .
Shape.java
public abstract class Shape implements Cloneable {

private String id;


protected String type;
abstract void draw();

public String getType(){


return type;
}

public String getId() {


return id;
}

public void setId(String id) {


this.id = id;
}

public Object clone() {


Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}

Paso 2
Crear clases concretas que amplíen la clase anterior.
Rectangle.java
public class Rectangle extends Shape {

public Rectangle(){
type = "Rectangle";
}

@Override
public void draw() {
System.out.println("Inside Rectangle::draw() method.");
}
}
Square.java
public class Square extends Shape {

public Square(){
type = "Square";
}

@Override
public void draw() {
System.out.println("Inside Square::draw() method.");
}
}
Circle.java
public class Circle extends Shape {

public Circle(){
type = "Circle";
}

@Override
public void draw() {
System.out.println("Inside Circle::draw() method.");
}
}

Paso 3
Cree una clase para obtener clases concéntricas de la base de datos y
almacénelas en una tabla hash .
ShapeCache.java
import java.util.Hashtable;

public class ShapeCache {

private static Hashtable<String, Shape> shapeMap


= new Hashtable<String, Shape>();

public static Shape getShape(String shapeId) {


Shape cachedShape = shapeMap.get(shapeId);
return (Shape) cachedShape.clone();
}

// for each shape run database query and create shape


// shapeMap.put(shapeKey, shape);
// for example, we are adding three shapes
public static void loadCache() {
Circle circle = new Circle();
circle.setId("1");
shapeMap.put(circle.getId(),circle);

Square square = new Square();


square.setId("2");
shapeMap.put(square.getId(),square);

Rectangle rectangle = new Rectangle();


rectangle.setId("3");
shapeMap.put(rectangle.getId(),rectangle);
}
}

Etapa 4
PrototypePatternDemo utiliza la clase ShapeCache para obtener clones de
formas almacenadas en una tabla hash .
PrototypePatternDemo.java
public class PrototypePatternDemo {
public static void main(String[] args) {
ShapeCache.loadCache();

Shape clonedShape = (Shape) ShapeCache.getShape("1");


System.out.println("Shape : " + clonedShape.getType());

Shape clonedShape2 = (Shape) ShapeCache.getShape("2");


System.out.println("Shape : " +
clonedShape2.getType());

Shape clonedShape3 = (Shape) ShapeCache.getShape("3");


System.out.println("Shape : " +
clonedShape3.getType());
}
}

Paso 5
Verifique la salida.
Forma: círculo
Forma: cuadrado
Forma: rectángulo
Patrón adaptador
El patrón del adaptador funciona como un puente entre dos interfaces
incompatibles. Este tipo de patrón de diseño viene bajo patrón estructural ya
que este patrón combina la capacidad de dos interfaces independientes.
Este patrón involucra una sola clase que es responsable de unir
funcionalidades de interfaces independientes o incompatibles. Un ejemplo de
la vida real podría ser un caso de lector de tarjetas que actúa como un
adaptador entre la tarjeta de memoria y una computadora portátil. Enchufa la
tarjeta de memoria en el lector de tarjetas y el lector de tarjetas en la
computadora portátil para que la tarjeta de memoria se pueda leer a través de
la computadora portátil.
Estamos demostrando el uso del patrón Adaptador a través del siguiente
ejemplo en el que un dispositivo reproductor de audio solo puede reproducir
archivos mp3 y quiere usar un reproductor de audio avanzado capaz de
reproducir archivos vlc y mp4.
Implementación
Tenemos una interfaz MediaPlayer y un AudioPlayer de clase concreta
que implementa la interfaz MediaPlayer . AudioPlayer puede reproducir
archivos de audio en formato mp3 de forma predeterminada.
Tenemos otra interfaz AdvancedMediaPlayer y clases concretas que
implementan la interfaz AdvancedMediaPlayer . Estas clases pueden
reproducir archivos en formato vlc y mp4.
Queremos que AudioPlayer también reproduzca otros formatos. Para lograr
esto, hemos creado una clase de adaptador MediaAdapter que implementa
la interfaz MediaPlayer y usa objetos AdvancedMediaPlayer para reproducir el
formato requerido.
AudioPlayer utiliza la clase de adaptador MediaAdapter y le pasa el tipo de
audio deseado sin conocer la clase real que puede reproducir el formato
deseado. AdapterPatternDemo , nuestra clase de demostración utilizará
la clase AudioPlayer para reproducir varios formatos.

Paso 1
Crear interfaces para Media Player y Advanced Media Player.
MediaPlayer.java
public interface MediaPlayer {
public void play(String audioType, String fileName);
}
AdvancedMediaPlayer.java
public interface AdvancedMediaPlayer {
public void playVlc(String fileName);
public void playMp4(String fileName);
}

Paso 2
Cree clases concretas implementando la interfaz AdvancedMediaPlayer .
VlcPlayer.java
public class VlcPlayer implements AdvancedMediaPlayer{
@Override
public void playVlc(String fileName) {
System.out.println("Playing vlc file. Name: "+
fileName);
}

@Override
public void playMp4(String fileName) {
//do nothing
}
}

Mp4Player.java
public class Mp4Player implements AdvancedMediaPlayer{

@Override
public void playVlc(String fileName) {
//do nothing
}

@Override
public void playMp4(String fileName) {
System.out.println("Playing mp4 file. Name: "+
fileName);
}
}

Paso 3
Cree una clase de adaptador que implemente la interfaz MediaPlayer .
MediaAdapter.java
public class MediaAdapter implements MediaPlayer {

AdvancedMediaPlayer advancedMusicPlayer;

public MediaAdapter(String audioType){


if(audioType.equalsIgnoreCase("vlc") ){
advancedMusicPlayer = new VlcPlayer();
} else if (audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer = new Mp4Player();
}
}

@Override
public void play(String audioType, String fileName) {
if(audioType.equalsIgnoreCase("vlc")){
advancedMusicPlayer.playVlc(fileName);
}else if(audioType.equalsIgnoreCase("mp4")){
advancedMusicPlayer.playMp4(fileName);
}
}
}

Etapa 4
Cree una clase concreta implementando la interfaz MediaPlayer .
AudioPlayer.java
public class AudioPlayer implements MediaPlayer {
MediaAdapter mediaAdapter;

@Override
public void play(String audioType, String fileName) {

//inbuilt support to play mp3 music files


if(audioType.equalsIgnoreCase("mp3")){
System.out.println("Playing mp3 file. Name: "+
fileName);
}
//mediaAdapter is providing support to play other file
formats
else if(audioType.equalsIgnoreCase("vlc")
|| audioType.equalsIgnoreCase("mp4")){
mediaAdapter = new MediaAdapter(audioType);
mediaAdapter.play(audioType, fileName);
}
else{
System.out.println("Invalid media. "+
audioType + " format not supported");
}
}
}

Paso 5
Use AudioPlayer para reproducir diferentes tipos de formatos de audio.
AdapterPatternDemo.java
public class AdapterPatternDemo {
public static void main(String[] args) {
AudioPlayer audioPlayer = new AudioPlayer();

audioPlayer.play("mp3", "beyond the horizon.mp3");


audioPlayer.play("mp4", "alone.mp4");
audioPlayer.play("vlc", "far far away.vlc");
audioPlayer.play("avi", "mind me.avi");
}
}

Paso 6
Verifique la salida.
Reproducción de archivos mp3. Nombre: más allá del
horizonte.mp3
Reproducción de archivo mp4. Nombre: alone.mp4
Reproducción de archivo vlc. Nombre: far far away.vlc
Medios inválidos. formato avi no compatible
Patrón de puente
Bridge se usa donde necesitamos desacoplar una abstracción de su
implementación para que los dos puedan variar independientemente. Este tipo
de patrón de diseño viene bajo un patrón estructural, ya que este patrón
desacopla la clase de implementación y la clase abstracta al proporcionar una
estructura de puente entre ellas.
Este patrón implica una interfaz que actúa como un puente que hace que la
funcionalidad de las clases concretas sea independiente de las clases
implementadoras de la interfaz. Ambos tipos de clases pueden modificarse
estructuralmente sin afectarse entre sí.
Estamos demostrando el uso del patrón Bridge a través del siguiente ejemplo
en el que se puede dibujar un círculo en diferentes colores usando el mismo
método de clase abstracta pero diferentes clases de implementador de
puente.

Implementación
Tenemos una interfaz de interfaz DrawAPI que actúa como implementador de
puentes y clases concretas RedCircle , GreenCircle implementando
la interfaz DrawAPI . Shape es una clase abstracta y utilizará el objeto
de DrawAPI . BridgePatternDemo , nuestra clase de demostración utilizará
la clase Shape para dibujar diferentes círculos de colores.
Paso 1
Crear interfaz de implementador de puente.
DrawAPI.java
public interface DrawAPI {
public void drawCircle(int radius, int x, int y);
}

Paso 2
Cree clases concretas de implementadores de puentes implementando
la interfaz DrawAPI .
RedCircle.java
public class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: red, radius:
"
+ radius +", x: " +x+", "+ y +"]");
}
}
GreenCircle.java
public class GreenCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle[ color: green,
radius: "
+ radius +", x: " +x+", "+ y +"]");
}
}

Paso 3
Cree una forma de clase abstracta utilizando la interfaz DrawAPI .
Shape.java
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI){
this.drawAPI = drawAPI;
}
public abstract void draw();
}

Etapa 4
Crea una clase concreta implementando la interfaz Shape .
Circle.java
public class Circle extends Shape {
private int x, y, radius;

public Circle(int x, int y, int radius, DrawAPI drawAPI) {


super(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}

public void draw() {


drawAPI.drawCircle(radius,x,y);
}
}

Paso 5
Use las clases Shape y DrawAPI para dibujar diferentes círculos de colores.
BridgePatternDemo.java
public class BridgePatternDemo {
public static void main(String[] args) {
Shape redCircle = new Circle(100,100, 10, new
RedCircle());
Shape greenCircle = new Circle(100,100, 10, new
GreenCircle());

redCircle.draw();
greenCircle.draw();
}
}

Paso 6
Verifique la salida.
Círculo de dibujo [color: rojo, radio: 10, x: 100, 100]
Círculo de dibujo [color: verde, radio: 10, x: 100, 100]
Patrón de filtro / criterio
El patrón de filtro o patrón de criterios es un patrón de diseño que permite a
los desarrolladores filtrar un conjunto de objetos, utilizando diferentes criterios,
encadenándolos de forma desacoplada a través de operaciones lógicas. Este
tipo de patrón de diseño viene bajo un patrón estructural ya que este patrón
combina múltiples criterios para obtener criterios únicos.

Implementación
Vamos a crear un objeto Persona , una interfaz de Criterios y clases concretas
que implementen esta interfaz para filtrar la lista
de objetos Persona . CriteriaPatternDemo , nuestra clase de demostración
utiliza objetos Criteria para filtrar los objetos de la Lista de personas en función
de varios criterios y sus combinaciones.

Paso 1
Cree una clase en la que se aplicarán los criterios.
Person.java
public class Person {

private String name;


private String gender;
private String maritalStatus;

public Person(String name,String gender,String


maritalStatus){
this.name = name;
this.gender = gender;
this.maritalStatus = maritalStatus;
}

public String getName() {


return name;
}
public String getGender() {
return gender;
}
public String getMaritalStatus() {
return maritalStatus;
}
}

Paso 2
Crear una interfaz para los criterios.
Criteria.java
import java.util.List;

public interface Criteria {


public List<Person> meetCriteria(List<Person> persons);
}

Paso 3
Crear clases concretas implementando la interfaz Criteria .
CriteriaMale.java
import java.util.ArrayList;
import java.util.List;

public class CriteriaMale implements Criteria {

@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> malePersons = new ArrayList<Person>();
for (Person person : persons) {
if(person.getGender().equalsIgnoreCase("MALE")){
malePersons.add(person);
}
}
return malePersons;
}
}

CriteriaFemale.java
import java.util.ArrayList;
import java.util.List;

public class CriteriaFemale implements Criteria {

@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> femalePersons = new ArrayList<Person>();
for (Person person : persons) {
if(person.getGender().equalsIgnoreCase("FEMALE")){
femalePersons.add(person);
}
}
return femalePersons;
}
}

CriteriaSingle.java
import java.util.ArrayList;
import java.util.List;

public class CriteriaSingle implements Criteria {

@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> singlePersons = new ArrayList<Person>();
for (Person person : persons) {

if(person.getMaritalStatus().equalsIgnoreCase("SINGLE")){
singlePersons.add(person);
}
}
return singlePersons;
}
}
AndCriteria.java
import java.util.List;

public class AndCriteria implements Criteria {


private Criteria criteria;
private Criteria otherCriteria;

public AndCriteria(Criteria criteria, Criteria


otherCriteria) {
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}

@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> firstCriteriaPersons =
criteria.meetCriteria(persons);
return
otherCriteria.meetCriteria(firstCriteriaPersons);
}
}

OrCriteria.java
import java.util.List;

public class AndCriteria implements Criteria {

private Criteria criteria;


private Criteria otherCriteria;

public AndCriteria(Criteria criteria, Criteria


otherCriteria) {
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}

@Override
public List<Person> meetCriteria(List<Person> persons) {
List<Person> firstCriteriaItems =
criteria.meetCriteria(persons);
List<Person> otherCriteriaItems =
otherCriteria.meetCriteria(persons);

for (Person person : otherCriteriaItems) {


if(!firstCriteriaItems.contains(person)){
firstCriteriaItems.add(person);
}
}
return firstCriteriaItems;
}
}

Etapa 4
Use diferentes criterios y su combinación para filtrar personas.
CriteriaPatternDemo.java
import java.util.ArrayList;
import java.util.List;

public class CriteriaPatternDemo {


public static void main(String[] args) {
List<Person> persons = new ArrayList<Person>();

persons.add(new Person("Robert","Male", "Single"));


persons.add(new Person("John","Male", "Married"));
persons.add(new Person("Laura","Female", "Married"));
persons.add(new Person("Diana","Female", "Single"));
persons.add(new Person("Mike","Male", "Single"));
persons.add(new Person("Bobby","Male", "Single"));

Criteria male = new CriteriaMale();


Criteria female = new CriteriaFemale();
Criteria single = new CriteriaSingle();
Criteria singleMale = new AndCriteria(single, male);
Criteria singleOrFemale = new OrCriteria(single,
female);

System.out.println("Males: ");
printPersons(male.meetCriteria(persons));

System.out.println("\nFemales: ");
printPersons(female.meetCriteria(persons));

System.out.println("\nSingle Males: ");


printPersons(singleMale.meetCriteria(persons));

System.out.println("\nSingle Or Females: ");


printPersons(singleOrFemale.meetCriteria(persons));
}

public static void printPersons(List<Person> persons){


for (Person person : persons) {
System.out.println("Person : [ Name : " +
person.getName()
+", Gender : " + person.getGender()
+", Marital Status : " +
person.getMaritalStatus()
+" ]");
}
}
}

Paso 5
Verifique la salida.
Machos:
Persona: [Nombre: Robert, Sexo: Masculino, Estado civil:
Soltero]
Persona: [Nombre: John, Sexo: Masculino, Estado civil:
Casado]
Persona: [Nombre: Mike, Sexo: Masculino, Estado civil:
Soltero]
Persona: [Nombre: Bobby, Sexo: Masculino, Estado civil:
Soltero]

Hembras:
Persona: [Nombre: Laura, Sexo: Femenino, Estado civil:
Casado]
Persona: [Nombre: Diana, Sexo: Femenino, Estado civil:
Soltero]

Hombres solteros:
Persona: [Nombre: Robert, Sexo: Masculino, Estado civil:
Soltero]
Persona: [Nombre: Mike, Sexo: Masculino, Estado civil:
Soltero]
Persona: [Nombre: Bobby, Sexo: Masculino, Estado civil:
Soltero]

Solteras o hembras:
Persona: [Nombre: Robert, Sexo: Masculino, Estado civil:
Soltero]
Persona: [Nombre: Diana, Sexo: Femenino, Estado civil:
Soltero]
Persona: [Nombre: Mike, Sexo: Masculino, Estado civil:
Soltero]
Persona: [Nombre: Bobby, Sexo: Masculino, Estado civil:
Soltero]
Persona: [Nombre: Laura, Sexo: Femenino, Estado civil:
Casado]
Patrón compuesto
El patrón compuesto se usa cuando necesitamos tratar un grupo de objetos de
manera similar como un solo objeto. El patrón compuesto compone objetos en
términos de una estructura de árbol para representar una jerarquía parcial y
completa. Este tipo de patrón de diseño viene bajo patrón estructural ya que
este patrón crea una estructura de árbol de grupo de objetos.
Este patrón crea una clase que contiene un grupo de sus propios objetos. Esta
clase proporciona formas de modificar su grupo de mismos objetos.
Estamos demostrando el uso del patrón compuesto mediante el siguiente
ejemplo en el que se muestra la jerarquía de empleados de una organización.

Implementación
Tenemos una clase Empleado que actúa como una clase de actor de patrón
compuesto. CompositePatternDemo , nuestra clase de demostración utilizará
la clase Employee para agregar la jerarquía de nivel de departamento e
imprimir a todos los empleados.

Paso 1
Crear clase de empleado con una lista de objetos de empleado .
Employee.java
import java.util.ArrayList;
import java.util.List;

public class Employee {


private String name;
private String dept;
private int salary;
private List<Employee> subordinates;

// constructor
public Employee(String name,String dept, int sal) {
this.name = name;
this.dept = dept;
this.salary = sal;
subordinates = new ArrayList<Employee>();
}

public void add(Employee e) {


subordinates.add(e);
}

public void remove(Employee e) {


subordinates.remove(e);
}

public List<Employee> getSubordinates(){


return subordinates;
}

public String toString(){


return ("Employee :[ Name : "+ name
+", dept : "+ dept + ", salary :"
+ salary+" ]");
}
}

Paso 2
Use la clase Employee para crear e imprimir la jerarquía de empleados.
CompositePatternDemo.java
public class CompositePatternDemo {
public static void main(String[] args) {
Employee CEO = new Employee("John","CEO", 30000);

Employee headSales = new Employee("Robert","Head


Sales", 20000);

Employee headMarketing = new Employee("Michel","Head


Marketing", 20000);

Employee clerk1 = new Employee("Laura","Marketing",


10000);
Employee clerk2 = new Employee("Bob","Marketing",
10000);

Employee salesExecutive1 = new


Employee("Richard","Sales", 10000);
Employee salesExecutive2 = new Employee("Rob","Sales",
10000);

CEO.add(headSales);
CEO.add(headMarketing);

headSales.add(salesExecutive1);
headSales.add(salesExecutive2);

headMarketing.add(clerk1);
headMarketing.add(clerk2);

//print all employees of the organization


System.out.println(CEO);
for (Employee headEmployee : CEO.getSubordinates()) {
System.out.println(headEmployee);
for (Employee employee :
headEmployee.getSubordinates()) {
System.out.println(employee);
}
}
}
}

Paso 3
Verifique la salida.
Empleado: [Nombre: John, departamento: CEO, salario: 30000]
Empleado: [Nombre: Robert, departamento: Jefe de ventas,
salario: 20000]
Empleado: [Nombre: Richard, departamento: Ventas, salario:
10000]
Empleado: [Nombre: Rob, departamento: Ventas, salario: 10000]
Empleado: [Nombre: Michel, departamento: Jefe de marketing,
salario: 20000]
Empleado: [Nombre: Laura, departamento: Marketing, salario:
10000]
Empleado: [Nombre: Bob, departamento: Marketing, salario:
10000]
Patrón decorador
El patrón de decorador permite agregar una nueva funcionalidad a un objeto
existente sin alterar su estructura. Este tipo de patrón de diseño viene bajo un
patrón estructural ya que este patrón actúa como un contenedor para la clase
existente.
Este patrón crea una clase de decorador que envuelve la clase original y
proporciona funcionalidad adicional manteniendo intactos los firmantes de los
métodos de clase.
Estamos demostrando el uso del patrón Decorator a través del siguiente
ejemplo en el que decoraremos una forma con algo de color sin alterar la clase
de forma.

Implementación
Vamos a crear una interfaz Shape y clases concretas implementando
la interfaz Shape . Luego creamos una clase de decorador
abstracto ShapeDecorator que implementa la interfaz Shape y que tiene
el objeto Shape como su variable de instancia.
RedShapeDecorator es una clase concreta que implementa ShapeDecorator .
DecoratorPatternDemo , nuestra clase de demostración
utilizará RedShapeDecorator para decorar objetos Shape .

Paso 1
Crea una interfaz.
Shape.java
public interface Shape {
void draw();
}

Paso 2
Crear clases concretas implementando la misma interfaz.
Rectangle.java
public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
Circle.java
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}

Paso 3
Crea una clase de decorador abstracto implementando la interfaz Shape .
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;

public ShapeDecorator(Shape decoratedShape){


this.decoratedShape = decoratedShape;
}

public void draw(){


decoratedShape.draw();
}
}

Etapa 4
Cree una clase de decorador concreto que amplíe la clase ShapeDecorator .
RedShapeDecorator.java
public class RedShapeDecorator extends ShapeDecorator {

public RedShapeDecorator(Shape decoratedShape) {


super(decoratedShape);
}

@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}

private void setRedBorder(Shape decoratedShape){


System.out.println("Border Color: Red");
}
}

Paso 5
Usa RedShapeDecorator para decorar objetos Shape .
DecoratorPatternDemo.java
public class DecoratorPatternDemo {
public static void main(String[] args) {

Shape circle = new Circle();

Shape redCircle = new RedShapeDecorator(new Circle());

Shape redRectangle = new RedShapeDecorator(new


Rectangle());
System.out.println("Circle with normal border");
circle.draw();

System.out.println("\nCircle of red border");


redCircle.draw();

System.out.println("\nRectangle of red border");


redRectangle.draw();
}
}

Paso 6
Verifique la salida.
Círculo con borde normal
Forma: círculo

Círculo de borde rojo


Forma: círculo
Color del borde: rojo

Rectángulo de borde rojo


Forma: rectángulo
Color del borde: rojo
Patrón de fachada
El patrón de fachada oculta las complejidades del sistema y proporciona una
interfaz para el cliente mediante la cual el cliente puede acceder al
sistema. Este tipo de patrón de diseño viene bajo un patrón estructural ya que
este patrón agrega una interfaz al sistema existente para ocultar sus
complejidades.
Este patrón involucra una sola clase que proporciona métodos simplificados
que son requeridos por el cliente y delega llamadas a los métodos de clases
del sistema existentes.

Implementación
Vamos a crear una interfaz Shape y clases concretas implementando
la interfaz Shape . Una clase de fachada ShapeMaker se define como el
siguiente paso.
La clase ShapeMaker utiliza las clases concretas para delegar las llamadas de
los usuarios a estas clases. FacadePatternDemo , nuestra clase de
demostración utilizará la clase ShapeMaker para mostrar los resultados.

Paso 1
Crea una interfaz.
Shape.java
public interface Shape {
void draw();
}

Paso 2
Crear clases concretas implementando la misma interfaz.
Rectangle.java
public class Rectangle implements Shape {

@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}

Square.java
public class Square implements Shape {

@Override
public void draw() {
System.out.println("Square::draw()");
}
}
Circle.java
public class Circle implements Shape {

@Override
public void draw() {
System.out.println("Circle::draw()");
}
}

Paso 3
Crea una clase de fachada.
ShapeMaker.java
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;

public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}

public void drawCircle(){


circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
public void drawSquare(){
square.draw();
}
}

Etapa 4
Usa la fachada para dibujar varios tipos de formas.
FacadePatternDemo.java
public class FacadePatternDemo {
public static void main(String[] args) {
ShapeMaker shapeMaker = new ShapeMaker();

shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
}
}

Paso 5
Verifique la salida.
Circle :: draw ()
Rectángulo :: dibujar ()
Cuadrado :: dibujar ()
Patrón de peso mosca
El patrón Flyweight se usa principalmente para reducir la cantidad de objetos
creados, para disminuir la huella de memoria y aumentar el rendimiento. Este
tipo de patrón de diseño viene bajo un patrón estructural ya que este patrón
proporciona formas de disminuir el recuento de objetos, mejorando así la
estructura de objetos requeridos por la aplicación.
El patrón Flyweight intenta reutilizar objetos similares ya existentes
almacenándolos y crea un nuevo objeto cuando no se encuentra ningún objeto
coincidente. Demostraremos este patrón dibujando 20 círculos de diferentes
ubicaciones, pero crearemos solo 5 objetos. Solo hay 5 colores disponibles,
por lo que la propiedad de color se utiliza para verificar los objetos Circle ya
existentes .

Implementación
Vamos a crear una interfaz Shape y un círculo de clase
concreto implementando la interfaz Shape . Una clase de
fábrica ShapeFactory se define como el siguiente paso.
ShapeFactory tiene un HashMap of Circle con clave como color
del objeto Circle . Cada vez que llega una solicitud para crear un círculo de
color particular para ShapeFactory . ShapeFactory comprueba el objeto del
círculo en su HashMap , si se encuentra el objeto del círculo , ese objeto se
devuelve; de lo contrario, se crea un nuevo objeto, se almacena en el
hashmap para uso futuro y se devuelve al cliente.
FlyWeightPatternDemo , nuestra clase de demostración
utilizará ShapeFactory para obtener un objeto Shape . Pasará información
( rojo / verde / azul / negro / blanco ) a ShapeFactory para obtener el círculo
del color deseado que necesita.
Paso 1
Crea una interfaz.
Shape.java
public interface Shape {
void draw();
}

Paso 2
Crea una clase concreta implementando la misma interfaz.
Circle.java
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;

public Circle(String color){


this.color = color;
}

public void setX(int x) {


this.x = x;
}

public void setY(int y) {


this.y = y;
}

public void setRadius(int radius) {


this.radius = radius;
}

@Override
public void draw() {
System.out.println("Circle: Draw() [Color : " + color
+", x : " + x +", y :" + y +", radius :" + radius);
}
}

Paso 3
Cree una Fábrica para generar objetos de clase concreta en función de la
información dada.
ShapeFactory.java
import java.util.HashMap;

public class ShapeFactory {

// Uncomment the compiler directive line and


// javac *.java will compile properly.
// @SuppressWarnings("unchecked")
private static final HashMap circleMap = new HashMap();

public static Shape getCircle(String color) {


Circle circle = (Circle)circleMap.get(color);

if(circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color : " +
color);
}
return circle;
}
}

Etapa 4
Use la Fábrica para obtener objetos de clase concreta al pasar información
como el color.
FlyweightPatternDemo.java
public class FlyweightPatternDemo {
private static final String colors[] =
{ "Red", "Green", "Blue", "White", "Black" };
public static void main(String[] args) {

for(int i=0; i < 20; ++i) {


Circle circle =
(Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
private static String getRandomColor() {
return colors[(int)(Math.random()*colors.length)];
}
private static int getRandomX() {
return (int)(Math.random()*100 );
}
private static int getRandomY() {
return (int)(Math.random()*100);
}
}

Paso 5
Verifique la salida.
Crear círculo de color: negro
Círculo: Draw () [Color: negro, x: 36, y: 71, radio: 100
Crear círculo de color: verde
Círculo: Draw () [Color: Verde, x: 27, y: 27, radio: 100
Crear círculo de color: blanco
Círculo: Draw () [Color: Blanco, x: 64, y: 10, radio: 100
Crear círculo de color: rojo
Círculo: Draw () [Color: Rojo, x: 15, y: 44, radio: 100
Círculo: Draw () [Color: Verde, x: 19, y: 10, radio: 100
Círculo: Draw () [Color: Verde, x: 94, y: 32, radio: 100
Círculo: Draw () [Color: Blanco, x: 69, y: 98, radio: 100
Crear círculo de color: azul
Círculo: Draw () [Color: Azul, x: 13, y: 4, radio: 100
Círculo: Draw () [Color: Verde, x: 21, y: 21, radio: 100
Círculo: Draw () [Color: Azul, x: 55, y: 86, radio: 100
Círculo: Draw () [Color: Blanco, x: 90, y: 70, radio: 100
Círculo: Draw () [Color: Verde, x: 78, y: 3, radio: 100
Círculo: Draw () [Color: Verde, x: 64, y: 89, radio: 100
Círculo: Draw () [Color: Azul, x: 3, y: 91, radio: 100
Círculo: Draw () [Color: Azul, x: 62, y: 82, radio: 100
Círculo: Draw () [Color: Verde, x: 97, y: 61, radio: 100
Círculo: Draw () [Color: Verde, x: 86, y: 12, radio: 100
Círculo: Draw () [Color: Verde, x: 38, y: 93, radio: 100
Círculo: Draw () [Color: Rojo, x: 76, y: 82, radio: 100
Círculo: Draw () [Color: Azul, x: 95, y: 82, radio: 100
Patrón Proxy
En el patrón Proxy, una clase representa la funcionalidad de otra clase. Este
tipo de patrón de diseño viene bajo patrón estructural.
En el patrón Proxy, creamos un objeto que tiene un objeto original para
interconectar su funcionalidad con el mundo exterior.

Implementación
Vamos a crear una interfaz de imagen y clases concretas que implementen
la interfaz de imagen . ProxyImage es una clase de proxy para reducir la
huella de memoria de la carga de objetos RealImage .
ProxyPatternDemo , nuestra clase de demostración utilizará ProxyImage para
obtener un objeto Image para cargar y mostrar según sea necesario.

Paso 1
Crea una interfaz.
Image.java
public interface Image {
void display();
}

Paso 2
Crear clases concretas implementando la misma interfaz.
RealImage.java
public class RealImage implements Image {

private String fileName;


public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}

@Override
public void display() {
System.out.println("Displaying " + fileName);
}

private void loadFromDisk(String fileName){


System.out.println("Loading " + fileName);
}
}
ProxyImage.java
public class ProxyImage implements Image{

private RealImage realImage;


private String fileName;

public ProxyImage(String fileName){


this.fileName = fileName;
}

@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}

Paso 3
Use ProxyImage para obtener el objeto de la clase RealImage cuando sea
necesario.
ProxyPatternDemo.java
public class ProxyPatternDemo {

public static void main(String[] args) {


Image image = new ProxyImage("test_10mb.jpg");

//image will be loaded from disk


image.display();
System.out.println("");
//image will not be loaded from disk
image.display();
}
}

Etapa 4
Verifique la salida.
Cargando test_10mb.jpg
Mostrando test_10mb.jpg

Mostrando test_10mb.jpg
Patrón de cadena de responsabilidad
Como su nombre indica, el patrón de la cadena de responsabilidad crea una
cadena de objetos receptores para una solicitud. Este patrón desacopla al
remitente y al receptor de una solicitud según el tipo de solicitud. Este patrón
viene bajo patrones de comportamiento.
En este patrón, normalmente cada receptor contiene referencia a otro
receptor. Si un objeto no puede manejar la solicitud, entonces pasa lo mismo
al siguiente receptor y así sucesivamente.

Implementación
Hemos creado una clase abstracta AbstractLogger con un nivel de
registro. Luego hemos creado tres tipos de registradores que extienden
el AbstractLogger . Cada registrador verifica el nivel del mensaje a su nivel e
imprime en consecuencia, de lo contrario no imprime y pasa el mensaje a su
próximo registrador.
Paso 1
Crear una clase de registrador abstracto.
AbstractLogger.java
public abstract class AbstractLogger {
public static int INFO = 1;
public static int DEBUG = 2;
public static int ERROR = 3;

protected int level;

//next element in chain or responsibility


protected AbstractLogger nextLogger;

public void setNextLogger(AbstractLogger nextLogger){


this.nextLogger = nextLogger;
}

public void logMessage(int level, String message){


if(this.level <= level){
write(message);
}
if(nextLogger !=null){
nextLogger.logMessage(level, message);
}
}

abstract protected void write(String message);

Paso 2
Crear clases concretas extendiendo el registrador.
ConsoleLogger.java
public class ConsoleLogger extends AbstractLogger {

public ConsoleLogger(int level){


this.level = level;
}

@Override
protected void write(String message) {
System.out.println("Standard Console::Logger: " +
message);
}
}
ErrorLogger.java
public class ErrorLogger extends AbstractLogger {

public ErrorLogger(int level){


this.level = level;
}

@Override
protected void write(String message) {
System.out.println("Error Console::Logger: " +
message);
}
}
FileLogger.java
public class FileLogger extends AbstractLogger {

public FileLogger(int level){


this.level = level;
}

@Override
protected void write(String message) {
System.out.println("File::Logger: " + message);
}
}

Paso 3
Crea diferentes tipos de registradores. Asigne niveles de error y configure el
siguiente registrador en cada registrador. El siguiente registrador en cada
registrador representa la parte de la cadena.
ChainPatternDemo.java
public class ChainPatternDemo {

private static AbstractLogger getChainOfLoggers(){

AbstractLogger errorLogger = new


ErrorLogger(AbstractLogger.ERROR);
AbstractLogger fileLogger = new
FileLogger(AbstractLogger.DEBUG);
AbstractLogger consoleLogger = new
ConsoleLogger(AbstractLogger.INFO);

errorLogger.setNextLogger(fileLogger);
fileLogger.setNextLogger(consoleLogger);

return errorLogger;
}

public static void main(String[] args) {


AbstractLogger loggerChain = getChainOfLoggers();

loggerChain.logMessage(AbstractLogger.INFO,
"This is an information.");

loggerChain.logMessage(AbstractLogger.DEBUG,
"This is an debug level information.");

loggerChain.logMessage(AbstractLogger.ERROR,
"This is an error information.");
}
}

Etapa 4
Verifique la salida.
Consola estándar :: Registrador: Esta es una información.
File :: Logger: esta es una información de nivel de
depuración.
Consola estándar :: Registrador: Esta es una información de
nivel de depuración.
Error Console :: Logger: Esta es una información de error.
File :: Logger: Esta es una información de error.
Consola estándar :: Registrador: Esta es una información de
error.
Patrón de comando
El patrón de comando es un patrón de diseño basado en datos y cae dentro
de la categoría de patrón de comportamiento. Una solicitud se envuelve bajo
un objeto como comando y se pasa al objeto invocador. El objeto Invoker
busca el objeto apropiado que puede manejar este comando y pasar el
comando al objeto correspondiente y ese objeto ejecuta el comando.

Implementación
Hemos creado una orden de interfaz que actúa como un comando. Hemos
creado un archivo de clase que actúa como una petición. Tenemos clases de
comando concretas BuyStock y SellStock que implementan la interfaz
de pedido que realizará el procesamiento de comando real. Se crea un Broker
de clase que actúa como un objeto invocador. Puede tomar pedidos y hacer
pedidos.
El objeto intermediario utiliza un patrón de comando para identificar qué objeto
ejecutará qué comando según el tipo de comando. CommandPatternDemo ,
nuestra clase de demostración utilizará la clase Broker para demostrar el
patrón de comando.
Paso 1
Crea una interfaz de comando.
Order.java
public interface Order {
void execute();
}

Paso 2
Crea una clase de solicitud.
Stock.java
public class Stock {

private String name = "ABC";


private int quantity = 10;

public void buy(){


System.out.println("Stock [ Name: "+name+",
Quantity: " + quantity +" ] bought");
}
public void sell(){
System.out.println("Stock [ Name: "+name+",
Quantity: " + quantity +" ] sold");
}
}

Paso 3
Crear clases concretas implementando la interfaz de pedido .
BuyStock.java
public class BuyStock implements Order {
private Stock abcStock;

public BuyStock(Stock abcStock){


this.abcStock = abcStock;
}

public void execute() {


abcStock.buy();
}
}

SellStock.java
public class SellStock implements Order {
private Stock abcStock;

public SellStock(Stock abcStock){


this.abcStock = abcStock;
}

public void execute() {


abcStock.sell();
}
}

Etapa 4
Crear clase de invocador de comandos.
Broker.java
import java.util.ArrayList;
import java.util.List;

public class Broker {


private List<Order> orderList = new ArrayList<Order>();

public void takeOrder(Order order){


orderList.add(order);
}

public void placeOrders(){


for (Order order : orderList) {
order.execute();
}
orderList.clear();
}
}

Paso 5
Use la clase Broker para tomar y ejecutar comandos.
CommandPatternDemo.java
public class CommandPatternDemo {
public static void main(String[] args) {
Stock abcStock = new Stock();

BuyStock buyStockOrder = new BuyStock(abcStock);


SellStock sellStockOrder = new SellStock(abcStock);

Broker broker = new Broker();


broker.takeOrder(buyStockOrder);
broker.takeOrder(sellStockOrder);

broker.placeOrders();
}
}

Paso 6
Verifique la salida.
Stock [Nombre: ABC, Cantidad: 10] comprado
Stock [Nombre: ABC, Cantidad: 10] vendido
Patrón de intérprete
El patrón de intérprete proporciona una forma de evaluar la gramática o
expresión del lenguaje. Este tipo de patrón viene bajo patrones de
comportamiento. Este patrón implica implementar una interfaz de expresión
que le dice que interprete un contexto particular. Este patrón se utiliza en el
análisis de SQL, el motor de procesamiento de símbolos, etc.

Implementación
Vamos a crear una interfaz Expresión y clases concretas que implementen
la interfaz Expresión . Se define una clase TerminalExpression que actúa
como un intérprete principal del contexto en cuestión. Otras
clases OrExpression , AndExpression se utilizan para crear expresiones
combinacionales.
InterpreterPatternDemo , nuestra clase de demostración
utilizará la clase Expression para crear reglas y demostrar el análisis de
expresiones.

Paso 1
Crea una interfaz de expresión.
Expression.java
public interface Expression {
public boolean interpret(String context);
}

Paso 2
Cree clases concretas implementando la interfaz anterior.
TerminalExpression.java
public class TerminalExpression implements Expression {

private String data;


public TerminalExpression(String data){
this.data = data;
}

@Override
public boolean interpret(String context) {
if(context.contains(data)){
return true;
}
return false;
}
}
OrExpression.java
public class OrExpression implements Expression {

private Expression expr1 = null;


private Expression expr2 = null;

public OrExpression(Expression expr1, Expression expr2) {


this.expr1 = expr1;
this.expr2 = expr2;
}

@Override
public boolean interpret(String context) {
return expr1.interpret(context) ||
expr2.interpret(context);
}
}
AndExpression.java
public class AndExpression implements Expression {

private Expression expr1 = null;


private Expression expr2 = null;

public AndExpression(Expression expr1, Expression expr2) {


this.expr1 = expr1;
this.expr2 = expr2;
}

@Override
public boolean interpret(String context) {
return expr1.interpret(context) &&
expr2.interpret(context);
}
}

Paso 3
InterpreterPatternDemo usa la clase Expression para crear reglas y luego
analizarlas.
InterpreterPatternDemo.java
public class InterpreterPatternDemo {

//Rule: Robert and John are male


public static Expression getMaleExpression(){
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
return new OrExpression(robert, john);
}

//Rule: Julie is a married women


public static Expression getMarriedWomanExpression(){
Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
}

public static void main(String[] args) {


Expression isMale = getMaleExpression();
Expression isMarriedWoman =
getMarriedWomanExpression();

System.out.println("John is male? " +


isMale.interpret("John"));
System.out.println("Julie is a married women? "
+ isMarriedWoman.interpret("Married Julie"));
}
}

Etapa 4
Verifique la salida.
John es hombre? cierto
Julie es una mujer casada? cierto
Patrón de iterador
El patrón iterador es un patrón de diseño muy utilizado en entornos de
programación Java y .Net. Este patrón se utiliza para obtener una forma de
acceder a los elementos de un objeto de colección de manera secuencial sin
necesidad de conocer su representación subyacente.
El patrón iterador cae en la categoría de patrón de comportamiento.

Implementación
Vamos a crear una interfaz Iterator que narra el método de navegación y
una interfaz Container que vuelve a ejecutar el iterador. Las clases concretas
que implementen la interfaz Contenedor serán responsables de implementar
la interfaz Iterator y usarla
IteratorPatternDemo , nuestra clase de demostración
utilizará NamesRepository , una implementación de clase concreta para
imprimir nombres almacenados como una colección en NamesRepository .

Paso 1
Crea interfaces.
Iterator.java
public interface Iterator {
public boolean hasNext();
public Object next();
}
Container.java
public interface Container {
public Iterator getIterator();
}

Paso 2
Crear una clase concreta implementando la interfaz de Contenedor . Esta
clase tiene clase interna NameIterator aplicación del iterador interfaz.
NameRepository.java
public class NameRepository implements Container {
public String names[] = {"Robert" , "John" ,"Julie" ,
"Lora"};

@Override
public Iterator getIterator() {
return new NameIterator();
}

private class NameIterator implements Iterator {

int index;

@Override
public boolean hasNext() {
if(index < names.length){
return true;
}
return false;
}

@Override
public Object next() {
if(this.hasNext()){
return names[index++];
}
return null;
}
}
}

Paso 3
Use el NameRepository para obtener iteradores e imprimir nombres.
IteratorPatternDemo.java
public class IteratorPatternDemo {

public static void main(String[] args) {


NameRepository namesRepository = new NameRepository();

for(Iterator iter = namesRepository.getIterator();


iter.hasNext();){
String name = (String)iter.next();
System.out.println("Name : " + name);
}
}
}

Etapa 4
Verifique la salida.
Nombre: Robert
Nombre: John
Nombre: Julie
Nombre: Lora
Patrón de mediador
El patrón de mediador se usa para reducir la complejidad de la comunicación
entre múltiples objetos o clases. Este patrón proporciona una clase de
mediador que normalmente maneja todas las comunicaciones entre diferentes
clases y admite una fácil mantenibilidad del código mediante un acoplamiento
flexible. El patrón de mediador cae en la categoría de patrón de
comportamiento.

Implementación
Estamos demostrando un patrón de mediador por ejemplo de una sala de chat
donde varios usuarios pueden enviar mensajes a la sala de chat y es
responsabilidad de la sala de chat mostrar los mensajes a todos los
usuarios. Hemos creado dos clases ChatRoom y Usuario . Los objetos
de usuario utilizarán el método ChatRoom para compartir sus mensajes.
MediatorPatternDemo , nuestra clase de demostración utilizará objetos
de usuario para mostrar la comunicación entre ellos.

Paso 1
Crear clase mediadora.
ChatRoom.java
import java.util.Date;

public class ChatRoom {


public static void showMessage(User user, String message){
System.out.println(new Date().toString()
+ " [" + user.getName() +"] : " + message);
}
}

Paso 2
Crear clase de usuario
User.java
public class User {
private String name;
public String getName() {
return name;
}

public void setName(String name) {


this.name = name;
}

public User(String name){


this.name = name;
}

public void sendMessage(String message){


ChatRoom.showMessage(this,message);
}
}

Paso 3
Use el objeto Usuario para mostrar las comunicaciones entre ellos.
MediatorPatternDemo.java
public class MediatorPatternDemo {
public static void main(String[] args) {
User robert = new User("Robert");
User john = new User("John");

robert.sendMessage("Hi! John!");
john.sendMessage("Hello! Robert!");
}
}

Etapa 4
Verifique la salida.
Jue 31 de enero 16:05:46 IST 2013 [Robert]: ¡Hola! ¡John!
Jue 31 de enero 16:05:46 IST 2013 [John]: ¡Hola! Robert!
Patrón de recuerdo
El patrón de recuerdo se usa para reducir dónde queremos restaurar el estado
de un objeto a un estado anterior. El patrón de recuerdo cae en la categoría de
patrón de comportamiento.

Implementación
El patrón de recuerdo utiliza tres clases de actores. El recuerdo contiene el
estado de un objeto a restaurar. El creador crea y almacena estados en los
objetos Memento y el objeto Caretaker que es responsable de restaurar el
estado del objeto desde Memento. Hemos creado las
clases Memento , Originator y CareTaker .
MementoPatternDemo , nuestra clase de demostración
utilizará objetos CareTaker y Originator para mostrar la restauración de los
estados de los objetos.

Paso 1
Crear clase de recuerdo.
Memento.java
public class Memento {
private String state;

public Memento(String state){


this.state = state;
}

public String getState(){


return state;
}
}

Paso 2
Crear clase de originador
Originator.java
public class Originator {
private String state;

public void setState(String state){


this.state = state;
}

public String getState(){


return state;
}

public Memento saveStateToMemento(){


return new Memento(state);
}

public void getStateFromMemento(Memento Memento){


state = memento.getState();
}
}

Paso 3
Crear clase CareTaker
CareTaker.java
import java.util.ArrayList;
import java.util.List;

public class CareTaker {


private List<Memento> mementoList = new
ArrayList<Memento>();

public void add(Memento state){


mementoList.add(state);
}

public Memento get(int index){


return mementoList.get(index);
}
}

Etapa 4
Use los objetos CareTaker y Originator .
MementoPatternDemo.java
public class MementoPatternDemo {
public static void main(String[] args) {
Originator originator = new Originator();
CareTaker careTaker = new CareTaker();
originator.setState("State #1");
originator.setState("State #2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State #4");

System.out.println("Current State: " +


originator.getState());
originator.getStateFromMemento(careTaker.get(0));
System.out.println("First saved State: " +
originator.getState());
originator.getStateFromMemento(careTaker.get(1));
System.out.println("Second saved State: " +
originator.getState());
}
}

Paso 5
Verifique la salida.
Estado actual: Estado # 4
Primer estado guardado: Estado # 2
Segundo Estado guardado: Estado # 3
Patrón de observador
El patrón de observador se usa cuando hay una relación de uno a muchos
entre los objetos, por ejemplo, si se modifica un objeto, sus objetos
dependientes deben ser notificados automáticamente. El patrón de observador
cae en la categoría de patrón de comportamiento.

Implementación
El patrón de observador utiliza tres clases de actores. Sujeto, observador y
cliente. Sujeto, un objeto que tiene métodos para adjuntar y desacoplar
observadores a un objeto cliente. Hemos creado clases de sujeto , clase
abstracta de observador y clases concretas que extienden la clase abstracta
al observador .
ObserverPatternDemo , nuestra clase de demostración utilizará objetos de
clase Asunto y concreto para mostrar el patrón de observador en acción.
Paso 1
Crear clase de asignatura.
Sujeto.java
import java.util.ArrayList;
import java.util.List;

public class Subject {

private List<Observer> observers


= new ArrayList<Observer>();
private int state;

public int getState() {


return state;
}

public void setState(int state) {


this.state = state;
notifyAllObservers();
}

public void attach(Observer observer){


observers.add(observer);
}

public void notifyAllObservers(){


for (Observer observer : observers) {
observer.update();
}
}
}

Paso 2
Crear clase de observador.
Observer.java
public abstract class Observer {
protected Subject subject;
public abstract void update();
}

Paso 3
Crear clases de observadores concretos
BinaryObserver.java
public class BinaryObserver extends Observer{

public BinaryObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Binary String: "
+ Integer.toBinaryString( subject.getState() ) );
}
}
OctalObserver.java
public class OctalObserver extends Observer{

public OctalObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Octal String: "
+ Integer.toOctalString( subject.getState() ) );
}
}

HexaObserver.java
public class HexaObserver extends Observer{

public HexaObserver(Subject subject){


this.subject = subject;
this.subject.attach(this);
}

@Override
public void update() {
System.out.println( "Hex String: "
+ Integer.toHexString( subject.getState()
).toUpperCase() );
}
}

Etapa 4
Usar sujetos y objetos de observación concretos.
ObserverPatternDemo.java
public class ObserverPatternDemo {
public static void main(String[] args) {
Subject subject = new Subject();

new HexaObserver(subject);
new OctalObserver(subject);
new BinaryObserver(subject);

System.out.println("First state change: 15");


subject.setState(15);
System.out.println("Second state change: 10");
subject.setState(10);
}
}

Paso 5
Verifique la salida.
Primer cambio de estado: 15
Cadena hexagonal: F
Cadena octal: 17
Cadena binaria: 1111
Segundo cambio de estado: 10
Cadena hexagonal: A
Cadena octal: 12
Cadena binaria: 1010
Patrón de estado
En el patrón de estado, el comportamiento de una clase cambia en función de
su estado. Este tipo de patrón de diseño viene bajo patrón de comportamiento.
En el patrón de estado, creamos objetos que representan varios estados y un
objeto de contexto cuyo comportamiento varía a medida que cambia su objeto
de estado.

Implementación
Vamos a crear una interfaz de estado que defina una acción y clases de
estado concretas que implementen la interfaz de estado . El contexto es una
clase que lleva un Estado.
StaePatternDemo , nuestra clase de demostración utilizará Context y objetos
de estado para demostrar el cambio en el comportamiento del Context basado
en el tipo de estado en el que se encuentra.

Paso 1
Crea una interfaz.
Image.java
public interface State {
public void doAction(Context context);
}

Paso 2
Crear clases concretas implementando la misma interfaz.
StartState.java
public class StartState implements State {

public void doAction(Context context) {


System.out.println("Player is in start state");
context.setState(this);
}

public String toString(){


return "Start State";
}
}

StopState.java
public class StopState implements State {

public void doAction(Context context) {


System.out.println("Player is in stop state");
context.setState(this);
}

public String toString(){


return "Stop State";
}
}

Paso 3
Crear clase de contexto .
Context.java
public class Context {
private State state;

public Context(){
state = null;
}

public void setState(State state){


this.state = state;
}

public State getState(){


return state;
}
}

Etapa 4
Use el contexto para ver cambios en el comportamiento cuando cambia
el estado .
StatePatternDemo.java
public class StatePatternDemo {
public static void main(String[] args) {
Context context = new Context();

StartState startState = new StartState();


startState.doAction(context);

System.out.println(context.getState().toString());

StopState stopState = new StopState();


stopState.doAction(context);

System.out.println(context.getState().toString());
}
}

Paso 5
Verifique la salida.
El jugador está en estado inicial
Estado de inicio
El jugador está en estado de parada
Estado de parada
Patrón de objeto nulo
En el patrón Objeto nulo, un objeto nulo reemplaza la comprobación de la
instancia del objeto NULO. En lugar de poner if check para un valor nulo, Null
Object refleja una relación de no hacer nada. Dicho objeto nulo también se
puede utilizar para proporcionar un comportamiento predeterminado en caso
de que los datos no estén disponibles.
En el patrón de objeto nulo, creamos una clase abstracta que especifica las
diversas operaciones que se deben realizar, clases concreadas que extienden
esta clase y una clase de objeto nulo que no proporciona ninguna
implementación de esta clase y se utilizará aparentemente cuando
necesitemos verificar el valor nulo.

Implementación
Vamos a crear una clase abstracta AbstractCustomer que define las
operaciones, aquí el nombre del cliente y las clases concretas que amplían
la clase AbstractCustomer . Se crea una CustomerFactory de clase de
fábrica para devolver objetos RealCustomer o NullCustomer en función del
nombre del cliente que se le ha pasado.
NullPatternDemo , nuestra clase de demostración
utilizará CustomerFactory para demostrar el uso del patrón de objeto nulo.
Paso 1
Crea una clase abstracta.
AbstractCustomer.java
public abstract class AbstractCustomer {
protected String name;
public abstract boolean isNil();
public abstract String getName();
}

Paso 2
Crear clases concretas que amplíen la clase anterior.
RealCustomer.java
public class RealCustomer extends AbstractCustomer {

public RealCustomer(String name) {


this.name = name;
}

@Override
public String getName() {
return name;
}

@Override
public boolean isNil() {
return false;
}
}
NullCustomer.java
public class NullCustomer extends AbstractCustomer {

@Override
public String getName() {
return "Not Available in Customer Database";
}

@Override
public boolean isNil() {
return true;
}
}

Paso 3
Crear clase de CustomerFactory .
CustomerFactory.java
public class CustomerFactory {

public static final String[] names = {"Rob", "Joe",


"Julie"};

public static AbstractCustomer getCustomer(String name){


for (int i = 0; i < names.length; i++) {
if (names[i].equalsIgnoreCase(name)){
return new RealCustomer(name);
}
}
return new NullCustomer();
}
}

Etapa 4
Utilice CustomerFactory
para obtener objetos RealCustomer o NullCustomer según el nombre del
cliente que se le haya pasado.
NullPatternDemo.java
public class NullPatternDemo {
public static void main(String[] args) {

AbstractCustomer customer1 =
CustomerFactory.getCustomer("Rob");
AbstractCustomer customer2 =
CustomerFactory.getCustomer("Bob");
AbstractCustomer customer3 =
CustomerFactory.getCustomer("Julie");
AbstractCustomer customer4 =
CustomerFactory.getCustomer("Laura");

System.out.println("Customers");
System.out.println(customer1.getName());
System.out.println(customer2.getName());
System.out.println(customer3.getName());
System.out.println(customer4.getName());
}
}

Paso 5
Verifique la salida.
Clientes
Robar
No disponible en la base de datos de clientes
Julie
No disponible en la base de datos de clientes
Patrón de estrategia
En el patrón de estrategia, un comportamiento de clase o su algoritmo se
puede cambiar en tiempo de ejecución. Este tipo de patrón de diseño viene
bajo patrón de comportamiento.
En el patrón de Estrategia, creamos objetos que representan diversas
estrategias y un objeto de contexto cuyo comportamiento varía según su
objeto de estrategia. El objeto de estrategia cambia el algoritmo de ejecución
del objeto de contexto.

Implementación
Vamos a crear una interfaz de Estrategia que defina una acción y clases de
estrategia concretas que implementen la interfaz de Estrategia . El contexto es
una clase que usa una estrategia.
StrategyPatternDemo , nuestra clase de demostración utilizará Context y
objetos de estrategia para demostrar el cambio en el comportamiento de
Context basado en la estrategia que implementa o utiliza.
Paso 1
Crea una interfaz.
Strategy.java
public interface Strategy {
public int doOperation(int num1, int num2);
}

Paso 2
Crear clases concretas implementando la misma interfaz.
OperationAdd.java
public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
OperationSubstract.java
public class OperationSubstract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}

OperationMultiply.java
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}

Paso 3
Crear clase de contexto .
Context.java
public class Context {
private Strategy strategy;

public Context(Strategy strategy){


this.strategy = strategy;
}

public int executeStrategy(int num1, int num2){


return strategy.doOperation(num1, num2);
}
}

Etapa 4
Use el contexto para ver un cambio en el comportamiento cuando cambia
su estrategia .
StatePatternDemo.java
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " +
context.executeStrategy(10, 5));

context = new Context(new OperationSubstract());


System.out.println("10 - 5 = " +
context.executeStrategy(10, 5));

context = new Context(new OperationMultiply());


System.out.println("10 * 5 = " +
context.executeStrategy(10, 5));
}
}

Paso 5
Verifique la salida.
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
Patrón de plantilla
En el patrón de plantilla, una clase abstracta expone formas definidas /
plantillas para ejecutar sus métodos. Sus subclases pueden anular las
implementaciones de métodos según las necesidades, pero la invocación
debe ser de la misma manera que la definida por una clase abstracta. Este
patrón entra en la categoría de patrón de comportamiento.

Implementación
Vamos a crear una clase abstracta de juego que defina operaciones con un
método de plantilla configurado como final para que no pueda ser
anulado. Cricket y fútbol son clases concretas que amplían el juego y anulan
sus métodos.
TemplatePatternDemo , nuestra clase de demostración usará Juego para
demostrar el uso del patrón de plantilla.

Paso 1
Cree una clase abstracta con un método de plantilla final.
Game.java
public abstract class Game {
abstract void initialize();
abstract void startPlay();
abstract void endPlay();

//template method
public final void play(){

//initialize the game


initialize();

//start game
startPlay();

//end game
endPlay();
}
}

Paso 2
Crear clases concretas que amplíen la clase anterior.
Cricket.java
public class Cricket extends Game {

@Override
void endPlay() {
System.out.println("Cricket Game Finished!");
}

@Override
void initialize() {
System.out.println("Cricket Game Initialized! Start
playing.");
}

@Override
void startPlay() {
System.out.println("Cricket Game Started. Enjoy the
game!");
}
}
Football.java
public class Football extends Game {
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}

@Override
void initialize() {
System.out.println("Football Game Initialized! Start
playing.");
}

@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the
game!");
}
}

Paso 3
Utilice el juego de la plantilla método play 's () para demostrar de una manera
definida de jugar el juego.
TemplatePatternDemo.java
public class TemplatePatternDemo {
public static void main(String[] args) {

Game game = new Cricket();


game.play();
System.out.println();
game = new Football();
game.play();
}
}

Etapa 4
Verifique la salida.
¡Juego de cricket inicializado! Empieza a jugar
Juego de cricket comenzado. ¡Disfruta el juego!
¡Juego de cricket terminado!

¡Juego de fútbol inicializado! Empieza a jugar


Juego de fútbol comenzó. ¡Disfruta el juego!
Juego de fútbol terminado!
Patrón de visitante
En el patrón Visitante, utilizamos una clase de visitante que cambia el
algoritmo de ejecución de una clase de elemento. De esta manera, el
algoritmo de ejecución del elemento puede variar a medida que varía el
visitante. Este patrón entra en la categoría de patrón de
comportamiento. Según el patrón, el objeto elemento debe aceptar el objeto
visitante para que el objeto visitante maneje la operación en el objeto
elemento.

Implementación
Vamos a crear una interfaz ComputerPart que defina la operación de
aceptación. El teclado , el mouse , el monitor y la computadora son clases
concretas que implementan la interfaz ComputerPart . Definiremos otra
interfaz ComputerPartVisitor que definirá las operaciones de una clase de
visitante. La computadora utiliza un visitante concreto para realizar la acción
correspondiente.
VisitorPatternDemo , nuestra clase de demostración utilizará las
clases Computer , ComputerPartVisitor para demostrar el uso del patrón de
visitante.

Paso 1
Definir una interfaz para representar el elemento.
ComputerPart.java
public interface class ComputerPart {
public void accept(ComputerPartVisitor
computerPartVisitor);
}

Paso 2
Crear clases concretas que amplíen la clase anterior.
Keyboard.java
public class Keyboard implements ComputerPart {

@Override
public void accept(ComputerPartVisitor
computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
Monitor.java
public class Monitor implements ComputerPart {

@Override
public void accept(ComputerPartVisitor
computerPartVisitor) {
computerPartVisitor.visit(this);
}
}

Mouse.java
public class Mouse implements ComputerPart {

@Override
public void accept(ComputerPartVisitor
computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
Computer.java
public class Computer implements ComputerPart {

ComputerPart[] parts;

public Computer(){
parts = new ComputerPart[] {new Mouse(), new
Keyboard(), new Monitor()};
}

@Override
public void accept(ComputerPartVisitor
computerPartVisitor) {
for (int i = 0; i < parts.length; i++) {
parts[i].accept(computerPartVisitor);
}
computerPartVisitor.visit(this);
}
}

Paso 3
Definir una interfaz para representar al visitante.
ComputerPartVisitor.java
public interface ComputerPartVisitor {
public void visit(Computer computer);
public void visit(Mouse mouse);
public void visit(Keyboard keyboard);
public void visit(Monitor monitor);
}

Etapa 4
Crear visitante concreto implementando la clase anterior.
ComputerPartDisplayVisitor.java
public class ComputerPartDisplayVisitor implements
ComputerPartVisitor {

@Override
public void visit(Computer computer) {
System.out.println("Displaying Computer.");
}

@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}

@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}

@Override
public void visit(Monitor monitor) {
System.out.println("Displaying Monitor.");
}
}

Paso 5
Use ComputerPartDisplayVisitor para mostrar partes de la computadora .
VisitorPatternDemo.java
public class VisitorPatternDemo {
public static void main(String[] args) {

ComputerPart computer = new Computer();


computer.accept(new ComputerPartDisplayVisitor());
}
}

Paso 6
Verifique la salida.
Mostrar el mouse.
Mostrar teclado.
Mostrar monitor.
Visualización de computadora.
Patrón MVC
Patrón MVC significa Modelo-Vista-Controlador Patrón. Este patrón se utiliza
para separar las preocupaciones de la aplicación.
 Modelo : el modelo representa un objeto o JAVA POJO que transporta
datos. También puede tener lógica para actualizar el controlador si sus datos
cambian.
 Ver : Ver representa la visualización de los datos que contiene el modelo.
 Controlador : el controlador actúa tanto en el modelo como en la vista. Controla el
flujo de datos en el objeto modelo y actualiza la vista cada vez que cambian los
datos. Mantiene Vista y Modelo separados.

Implementación
Vamos a crear un objeto Estudiante que actúe como
modelo. StudentView será una clase de vista que puede imprimir los detalles
del estudiante en la consola y StudentController es la clase de controlador
responsable de almacenar datos en el objeto Student y actualizar la
vista StudentView en consecuencia.
MVCPatternDemo , nuestra clase de demostración
utilizará StudentController para demostrar el uso del patrón MVC.
Paso 1
Crear modelo
Estudiante.java
public class Student {
private String rollNo;
private String name;
public String getRollNo() {
return rollNo;
}
public void setRollNo(String rollNo) {
this.rollNo = rollNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

Paso 2
Crear vista.
StudentView.java
public class StudentView {
public void printStudentDetails(String studentName, String
studentRollNo){
System.out.println("Student: ");
System.out.println("Name: " + studentName);
System.out.println("Roll No: " + studentRollNo);
}
}

Paso 3
Crear controlador.
StudentController.java
public class StudentController {
private Student model;
private StudentView view;

public StudentController(Student model, StudentView view){


this.model = model;
this.view = view;
}

public void setStudentName(String name){


model.setName(name);
}

public String getStudentName(){


return model.getName();
}

public void setStudentRollNo(String rollNo){


model.setRollNo(rollNo);
}

public String getStudentRollNo(){


return model.getRollNo();
}

public void updateView(){


view.printStudentDetails(model.getName(),
model.getRollNo());
}
}

Etapa 4
Use los métodos StudentController para demostrar el uso del patrón de diseño
MVC.
MVCPatternDemo.java
public class MVCPatternDemo {
public static void main(String[] args) {

//fetch student record based on his roll no from the


database
Student model = retriveStudentFromDatabase();

//Create a view : to write student details on console


StudentView view = new StudentView();

StudentController controller = new


StudentController(model, view);

controller.updateView();

//update model data


controller.setStudentName("John");

controller.updateView();
}

private static Student retriveStudentFromDatabase(){


Student student = new Student();
student.setName("Robert");
student.setRollNo("10");
return student;
}
}

Paso 5
Verifique la salida.
Estudiante:
Nombre: Robert
Rollo No: 10
Estudiante:
Nombre: Julie
Rollo No: 10
Patrón de delegado comercial
El patrón de delegado comercial se utiliza para desacoplar el nivel de
presentación y el nivel comercial. Básicamente se utiliza para reducir la
comunicación o la funcionalidad de búsqueda remota al código de nivel
empresarial en el código de nivel de presentación. En el nivel empresarial,
hemos seguido las entidades.
 Cliente : el código del nivel de presentación puede ser JSP, servlet o código Java
UI.
 Delegado comercial : una clase de punto de entrada único para que las
entidades cliente proporcionen acceso a los métodos del Servicio comercial.
 Servicio de búsqueda: el objeto del servicio de búsqueda es responsable de
obtener una implementación comercial relativa y proporcionar acceso a los
objetos comerciales al objeto delegado comercial.
 Servicio comercial: interfaz de servicio comercial. Las clases concretas
implementan este servicio comercial para proporcionar una lógica de
implementación comercial real.

Implementación
Vamos a crear
un Cliente , BusinessDelegate , BusinessService , LookUpService , JMSServic
e y EJBService que representan varias entidades del patrón Business
Delegate.
BusinessDelegatePatternDemo , nuestra clase de demostración
utilizará BusinessDelegate y Client para demostrar el uso del patrón Business
Delegate.

Paso 1
Crear interfaz de BusinessService.
BusinessService.java
public interface BusinessService {
public void doProcessing();
}
Paso 2
Crear clases de servicio concisa.
EJBService.java
public class EJBService implements BusinessService {

@Override
public void doProcessing() {
System.out.println("Processing task by invoking EJB
Service");
}
}
JMSService.java
public class JMSService implements BusinessService {

@Override
public void doProcessing() {
System.out.println("Processing task by invoking JMS
Service");
}
}

Paso 3
Crear servicio de búsqueda de negocios.
BusinessLookUp.java
public class BusinessLookUp {
public BusinessService getBusinessService(String
serviceType){
if(serviceType.equalsIgnoreCase("EJB")){
return new EJBService();
}else {
return new JMSService();
}
}
}

Etapa 4
Crear delegado comercial.
BusinessLookUp.java
public class BusinessDelegate {
private BusinessLookUp lookupService = new
BusinessLookUp();
private BusinessService businessService;
private String serviceType;

public void setServiceType(String serviceType){


this.serviceType = serviceType;
}

public void doTask(){


businessService =
lookupService.getBusinessService(serviceType);
businessService.doProcessing();
}
}

Paso 5
Crear cliente.
Estudiante.java
public class Client {

BusinessDelegate businessService;

public Client(BusinessDelegate businessService){


this.businessService = businessService;
}

public void doTask(){


businessService.doTask();
}
}

Paso 6
Utilice las clases BusinessDelegate y Client para demostrar el patrón Business
Delegate.
BusinessDelegatePatternDemo.java
public class BusinessDelegatePatternDemo {

public static void main(String[] args) {

BusinessDelegate businessDelegate = new


BusinessDelegate();
businessDelegate.setServiceType("EJB");

Client client = new Client(businessDelegate);


client.doTask();

businessDelegate.setServiceType("JMS");
client.doTask();
}
}

Paso 7
Verifique la salida.
Procesar tarea invocando el servicio EJB
Tarea de procesamiento invocando el servicio JMS
Patrón de entidad compuesta
El patrón de entidad compuesta se usa en el mecanismo de persistencia
EJB. Una entidad compuesta es un bean de entidad EJB que representa un
gráfico de objetos. Cuando se actualiza una entidad compuesta, los beans de
objetos dependientes internamente se actualizan automáticamente como
gestionados por el bean de entidad EJB. Los siguientes son los participantes
en Composite Entity Bean.
 Entidad compuesta : es un bean de entidad primaria. Puede ser de grano grueso
o puede contener un objeto de grano grueso para ser utilizado con fines de
persistencia.
 Objeto de grano grueso: este objeto contiene objetos dependientes. Tiene su
propio ciclo de vida y también gestiona el ciclo de vida de los objetos
dependientes.
 Objeto dependiente: los objetos dependientes son un objeto que depende del
objeto de grano grueso para su ciclo de vida de persistencia.
 Estrategias : las estrategias representan cómo implementar una entidad
compuesta.

Implementación
Vamos a crear un objeto CompositeEntity que actúe como
CompositeEntity. CoarseGrainedObject será una clase que contiene objetos
dependientes. CompositeEntityPatternDemo , nuestra clase de demostración
utilizará la clase Cliente para demostrar el uso del patrón de Entidad
Compuesta.
Paso 1
Crear objetos dependientes.
DependentObject1.java
public class DependentObject1 {

private String data;

public void setData(String data){


this.data = data;
}

public String getData(){


return data;
}
}
DependentObject2.java
public class DependentObject2 {

private String data;

public void setData(String data){


this.data = data;
}

public String getData(){


return data;
}
}

Paso 2
Crear objeto de grano grueso.
CoarseGrainedObject.java
public class CoarseGrainedObject {
DependentObject1 do1 = new DependentObject1();
DependentObject2 do2 = new DependentObject2();

public void setData(String data1, String data2){


do1.setData(data1);
do2.setData(data2);
}

public String[] getData(){


return new String[] {do1.getData(),do2.getData()};
}
}

Paso 3
Crear entidad compuesta.
CompositeEntity.java
public class CompositeEntity {
private CoarseGrainedObject cgo = new
CoarseGrainedObject();

public void setData(String data1, String data2){


cgo.setData(data1, data2);
}

public String[] getData(){


return cgo.getData();
}
}

Etapa 4
Crear clase de cliente para usar Entidad compuesta.
Client.java
public class Client {
private CompositeEntity compositeEntity = new
CompositeEntity();
public void printData(){
for (int i = 0; i < compositeEntity.getData().length;
i++) {
System.out.println("Data: " +
compositeEntity.getData()[i]);
}
}

public void setData(String data1, String data2){


compositeEntity.setData(data1, data2);
}
}

Paso 5
Use el Cliente para demostrar el uso del patrón de diseño de la entidad
compuesta.
CompositeEntityPatternDemo.java
public class CompositeEntityPatternDemo {
public static void main(String[] args) {
Client client = new Client();
client.setData("Test", "Data");
client.printData();
client.setData("Second Test", "Data1");
client.printData();
}
}

Paso 6
Verifique la salida.
Datos: prueba
Datos: datos
Datos: segunda prueba
Datos: Datos1
Patrón de objeto de acceso a datos
El patrón de objetos de acceso a datos o el patrón DAO se utilizan para
separar las operaciones o API de acceso a datos de bajo nivel de los servicios
empresariales de alto nivel. Los siguientes son los participantes en el patrón
de objetos de acceso a datos.
 Interfaz de objeto de acceso a datos : esta interfaz define las operaciones
estándar que se realizarán en un objeto (s) modelo.
 Clase concreta del objeto de acceso a datos: esta clase implementa la interfaz
anterior. Esta clase es responsable de obtener datos de una fuente de datos que
puede ser base de datos / xml o cualquier otro mecanismo de almacenamiento.
 Objeto modelo u objeto de valor : este objeto es un POJO simple que contiene
métodos get / set para almacenar datos recuperados utilizando la clase DAO.

Implementación
Vamos a crear un objeto Estudiante que actúe como un Modelo u Objeto de
valor. StudentDao es la interfaz de objetos de acceso a
datos. StudentDaoImpl es una clase concreta que implementa la interfaz de
objetos de acceso a datos. DaoPatternDemo , nuestra clase de demostración
utilizará StudentDao demostrar el uso del modelo de objetos de acceso a
datos.

Paso 1
Crear objeto de valor.
Estudiante.java
public class Student {
private String name;
private int rollNo;

Student(String name, int rollNo){


this.name = name;
this.rollNo = rollNo;
}

public String getName() {


return name;
}
public void setName(String name) {
this.name = name;
}

public int getRollNo() {


return rollNo;
}

public void setRollNo(int rollNo) {


this.rollNo = rollNo;
}
}

Paso 2
Crear interfaz de objeto de acceso a datos.
StudentDao.java
import java.util.List;

public interface StudentDao {


public List<Student> getAllStudents();
public Student getStudent(int rollNo);
public void updateStudent(Student student);
public void deleteStudent(Student student);
}

Paso 3
Crear clase concreada implementando la interfaz anterior.
StudentDaoImpl.java
import java.util.ArrayList;
import java.util.List;

public class StudentDaoImpl implements StudentDao {

//list is working as a database


List<Student> students;

public StudentDaoImpl(){
students = new ArrayList<Student>();
Student student1 = new Student("Robert",0);
Student student2 = new Student("John",1);
students.add(student1);
students.add(student2);
}
@Override
public void deleteStudent(Student student) {
students.remove(student.getRollNo());
System.out.println("Student: Roll No " +
student.getRollNo()
+", deleted from database");
}

//retrive list of students from the database


@Override
public List<Student> getAllStudents() {
return students;
}

@Override
public Student getStudent(int rollNo) {
return students.get(rollNo);
}

@Override
public void updateStudent(Student student) {

students.get(student.getRollNo()).setName(student.getName());
System.out.println("Student: Roll No " +
student.getRollNo()
+", updated in the database");
}
}

Etapa 4
Use el " StudentDao" para demostrar el uso del patrón de objeto de acceso a
datos.
CompositeEntityPatternDemo.java
public class DaoPatternDemo {
public static void main(String[] args) {
StudentDao studentDao = new StudentDaoImpl();

//print all students


for (Student student : studentDao.getAllStudents()) {
System.out.println("Student: [RollNo : "
+student.getRollNo()+", Name :
"+student.getName()+" ]");
}

//update student
Student student =studentDao.getAllStudents().get(0);
student.setName("Michael");
studentDao.updateStudent(student);

//get the student


studentDao.getStudent(0);
System.out.println("Student: [RollNo : "
+student.getRollNo()+", Name : "+student.getName()+"
]");
}
}

Paso 5
Verifique la salida.
Estudiante: [Rollo No: 0, Nombre: Robert]
Estudiante: [Rollo No: 1, Nombre: John]
Estudiante: Roll No 0, actualizado en la base de datos
Estudiante: [Número de rollo: 0, Nombre: Michael]
Patrón de controlador frontal
El patrón de diseño del controlador frontal se utiliza para proporcionar un
mecanismo centralizado de manejo de solicitudes para que todas las
solicitudes sean manejadas por un solo manejador. Este controlador puede
realizar la autenticación / autorización / registro o seguimiento de la solicitud y
luego pasar las solicitudes a los controladores correspondientes. Las
siguientes son las entidades de este tipo de patrón de diseño.
 Controlador frontal: controlador único para todo tipo de solicitud que llega a la
aplicación (ya sea basada en la web / en el escritorio).
 Despachador : el controlador frontal puede usar un objeto despachador que
puede enviar la solicitud al controlador específico correspondiente.
 Vista : las vistas son el objeto para el que se realizan las solicitudes.

Implementación
Vamos a crear un FrontController , Dispatcher para que actúe como Front
Controller y Dispatcher
correspondientemente. Homeview y StudentView representan diversas vistas
para los que las peticiones pueden venir a controlador frontal.
FrontControllerPatternDemo , nuestra clase de demostración
utilizará FrontController para demostrar el Patrón de diseño del controlador
frontal.
Paso 1
Crear vistas
HomeView.java
public class HomeView {
public void show(){
System.out.println("Displaying Home Page");
}
}
StudentView.java
public class StudentView {
public void show(){
System.out.println("Displaying Student Page");
}
}

Paso 2
Crear despachador.
Dispatcher.java
public class Dispatcher {
private StudentView studentView;
private HomeView homeView;
public Dispatcher(){
studentView = new StudentView();
homeView = new HomeView();
}

public void dispatch(String request){


if(request.equalsIgnoreCase("STUDENT")){
studentView.show();
}else{
homeView.show();
}
}
}

Paso 3
Crear FrontController
Context.java
public class FrontController {

private Dispatcher dispatcher;

public FrontController(){
dispatcher = new Dispatcher();
}

private boolean isAuthenticUser(){


System.out.println("User is authenticated
successfully.");
return true;
}

private void trackRequest(String request){


System.out.println("Page requested: " + request);
}

public void dispatchRequest(String request){


//log each request
trackRequest(request);
//authenticate the user
if(isAuthenticUser()){
dispatcher.dispatch(request);
}
}
}

Etapa 4
Use el FrontController para demostrar el Patrón de diseño del controlador
frontal.
FrontControllerPatternDemo.java
public class FrontControllerPatternDemo {
public static void main(String[] args) {
FrontController frontController = new
FrontController();
frontController.dispatchRequest("HOME");
frontController.dispatchRequest("STUDENT");
}
}

Paso 5
Verifique la salida.
Página solicitada: INICIO
El usuario se autentica correctamente.
Mostrar página de inicio
Página solicitada: ESTUDIANTE
El usuario se autentica correctamente.
Mostrar página del alumno
Patrón de filtro interceptor
El patrón de diseño del filtro interceptor se utiliza cuando queremos hacer un
procesamiento previo / posterior con la solicitud o respuesta de la
aplicación. Los filtros se definen y aplican en la solicitud antes de pasar la
solicitud a la aplicación de destino real. Los filtros pueden realizar la
autenticación / autorización / registro o seguimiento de la solicitud y luego
pasar las solicitudes a los controladores correspondientes. Las siguientes son
las entidades de este tipo de patrón de diseño.
 Filtro : filtro que realizará cierta tarea antes o después de la ejecución de la
solicitud por parte del controlador de solicitudes.
 Cadena de filtro: la cadena de filtro lleva varios filtros y ayuda a ejecutarlos en un
orden definido en el objetivo.
 Destino : el objeto de destino es el manejador de solicitudes
 Administrador de filtros: el Administrador de filtros administra los filtros y la
cadena de filtros.
 Cliente : el cliente es el objeto que envía la solicitud al objeto de destino.

Implementación
Vamos a crear un FilterChain , FilterManager , Target , Client como varios
objetos que representan nuestras
entidades. AuthenticationFilter y DebugFilter representan filtros concretos.
InterceptingFilterDemo , nuestra clase de demostración utilizará el Cliente para
demostrar el Patrón de diseño de filtro de interceptación.
Paso 1
Crear interfaz de filtro.
Filter.java
public interface Filter {
public void execute(String request);
}

Paso 2
Crea filtros de hormigón.
AuthenticationFilter.java
public class AuthenticationFilter implements Filter {
public void execute(String request){
System.out.println("Authenticating request: " +
request);
}
}
DebugFilter.java
public class DebugFilter implements Filter {
public void execute(String request){
System.out.println("request log: " + request);
}
}

Paso 3
Crear objetivo
Target.java
public class Target {
public void execute(String request){
System.out.println("Executing request: " + request);
}
}

Etapa 4
Crear cadena de filtro
FilterChain.java
import java.util.ArrayList;
import java.util.List;

public class FilterChain {


private List<Filter> filters = new ArrayList<Filter>();
private Target target;

public void addFilter(Filter filter){


filters.add(filter);
}

public void execute(String request){


for (Filter filter : filters) {
filter.execute(request);
}
target.execute(request);
}

public void setTarget(Target target){


this.target = target;
}
}

Paso 5
Crear administrador de filtros
FilterManager.java
public class FilterManager {
FilterChain filterChain;

public FilterManager(Target target){


filterChain = new FilterChain();
filterChain.setTarget(target);
}
public void setFilter(Filter filter){
filterChain.addFilter(filter);
}

public void filterRequest(String request){


filterChain.execute(request);
}
}

Paso 6
Crear cliente
Client.java
public class Client {
FilterManager filterManager;

public void setFilterManager(FilterManager filterManager){


this.filterManager = filterManager;
}

public void sendRequest(String request){


filterManager.filterRequest(request);
}
}

Paso 7
Use el Cliente para demostrar el patrón de diseño de filtro interceptor.
FrontControllerPatternDemo.java
public class InterceptingFilterDemo {
public static void main(String[] args) {
FilterManager filterManager = new FilterManager(new
Target());
filterManager.setFilter(new AuthenticationFilter());
filterManager.setFilter(new DebugFilter());

Client client = new Client();


client.setFilterManager(filterManager);
client.sendRequest("HOME");
}
}
Paso 8
Verifique la salida.
Solicitud de autenticación: INICIO
registro de solicitud: INICIO
Solicitud de ejecución: INICIO
Patrón de localizador de servicio
El patrón de diseño del localizador de servicios se usa cuando queremos
ubicar varios servicios usando la búsqueda JNDI. Considerando el alto costo
de buscar JNDI para un servicio, el patrón de Localizador de Servicio hace uso
de la técnica de almacenamiento en caché. Por primera vez se requiere un
servicio, Service Locator busca en JNDI y almacena en caché el objeto de
servicio. La búsqueda adicional o el mismo servicio a través del Localizador de
servicios se realiza en su caché, lo que mejora el rendimiento de la aplicación
en gran medida. Las siguientes son las entidades de este tipo de patrón de
diseño.
 Servicio : servicio real que procesará la solicitud. La referencia de dicho servicio
debe considerarse en el servidor JNDI.
 Contexto / Contexto inicial -JNDI Context, lleva la referencia al servicio utilizado
para fines de búsqueda.
 Service Locator : Service Locator es un único punto de contacto para obtener
servicios mediante la búsqueda JNDI, almacenando en caché los servicios.
 Caché - Caché para almacenar referencias de servicios para reutilizarlos
 Cliente : el cliente es el objeto que invoca los servicios a través de ServiceLocator.

Implementación
Vamos a crear un ServiceLocator , InitialContext , Cache , Service como varios
objetos que representan nuestras entidades. Service1 y Service2 representan
servicios concretos.
ServiceLocatorPatternDemo , nuestra clase de demostración está actuando
como cliente aquí y utilizará ServiceLocator para demostrar el patrón de
diseño del localizador de servicios.
Paso 1
Crear interfaz de servicio.
Service.java
public interface Service {
public String getName();
public void execute();
}

Paso 2
Crear servicios concretos.
Service1.java
public class Service1 implements Service {
public void execute(){
System.out.println("Executing Service1");
}

@Override
public String getName() {
return "Service1";
}
}
Service2.java
public class Service2 implements Service {
public void execute(){
System.out.println("Executing Service2");
}

@Override
public String getName() {
return "Service2";
}
}

Paso 3
Crear InitialContext para búsqueda JNDI
InitialContext.java
public class InitialContext {
public Object lookup(String jndiName){
if(jndiName.equalsIgnoreCase("SERVICE1")){
System.out.println("Looking up and creating a new
Service1 object");
return new Service1();
}else if (jndiName.equalsIgnoreCase("SERVICE2")){
System.out.println("Looking up and creating a new
Service2 object");
return new Service2();
}
return null;
}
}

Etapa 4
Crear caché
Cache.java
import java.util.ArrayList;
import java.util.List;

public class Cache {

private List<Service> services;

public Cache(){
services = new ArrayList<Service>();
}
public Service getService(String serviceName){
for (Service service : services) {
if(service.getName().equalsIgnoreCase(serviceName)){
System.out.println("Returning cached
"+serviceName+" object");
return service;
}
}
return null;
}

public void addService(Service newService){


boolean exists = false;
for (Service service : services) {

if(service.getName().equalsIgnoreCase(newService.getName())){
exists = true;
}
}
if(!exists){
services.add(newService);
}
}
}

Paso 5
Crear localizador de servicios
ServiceLocator.java
public class ServiceLocator {
private static Cache cache;

static {
cache = new Cache();
}

public static Service getService(String jndiName){

Service service = cache.getService(jndiName);

if(service != null){
return service;
}

InitialContext context = new InitialContext();


Service service1 = (Service)context.lookup(jndiName);
cache.addService(service1);
return service1;
}
}

Paso 6
Use el ServiceLocator para demostrar el patrón de diseño del localizador de
servicios.
ServiceLocatorPatternDemo.java
public class ServiceLocatorPatternDemo {
public static void main(String[] args) {
Service service =
ServiceLocator.getService("Service1");
service.execute();
service = ServiceLocator.getService("Service2");
service.execute();
service = ServiceLocator.getService("Service1");
service.execute();
service = ServiceLocator.getService("Service2");
service.execute();
}
}

Paso 7
Verifique la salida.
Buscar y crear un nuevo objeto Service1
Servicio ejecutor1
Buscar y crear un nuevo objeto Service2
Servicio de ejecución2
Devolver el objeto Service1 en caché
Servicio ejecutor1
Devolver el objeto Service2 en caché
Servicio de ejecución2
Transferir patrón de objeto
El patrón Transferir objeto se usa cuando queremos pasar datos con múltiples
atributos de una sola vez de cliente a servidor. El objeto de transferencia
también se conoce como objeto de valor. Transfer Object es una clase POJO
simple que tiene métodos getter / setter y es serializable para que pueda
transferirse a través de la red. No tiene ningún comportamiento. La clase de
negocios del lado del servidor normalmente obtiene datos de la base de datos
y llena el POJO y lo envía al cliente o lo pasa por valor. Para el cliente, el
objeto de transferencia es de solo lectura. El cliente puede crear su propio
objeto de transferencia y pasarlo al servidor para actualizar los valores en la
base de datos de una sola vez. Las siguientes son las entidades de este tipo
de patrón de diseño.
 Objeto comercial: servicio comercial que llena el objeto de transferencia con
datos.
 Transferir objeto : POJO simple, que tiene métodos para establecer / obtener
atributos solamente.
 Cliente : el cliente solicita o envía el objeto de transferencia al objeto comercial.

Implementación
Vamos a crear un StudentBO como objeto comercial, el estudiante como
objeto de transferencia que representa nuestras entidades.
TransferObjectPatternDemo , nuestra clase de demostración está actuando
como un cliente aquí y utilizará StudentBO y Student para demostrar el patrón
de diseño de transferencia de objetos.

Paso 1
Crear objeto de transferencia.
StudentVO.java
public class StudentVO {
private String name;
private int rollNo;

StudentVO(String name, int rollNo){


this.name = name;
this.rollNo = rollNo;
}

public String getName() {


return name;
}
public void setName(String name) {
this.name = name;
}

public int getRollNo() {


return rollNo;
}

public void setRollNo(int rollNo) {


this.rollNo = rollNo;
}
}

Paso 2
Crear objeto comercial.
StudentBO.java
import java.util.ArrayList;
import java.util.List;

public class StudentBO {

//list is working as a database


List<StudentVO> students;

public StudentBO(){
students = new ArrayList<StudentVO>();
StudentVO student1 = new StudentVO("Robert",0);
StudentVO student2 = new StudentVO("John",1);
students.add(student1);
students.add(student2);
}
public void deleteStudent(StudentVO student) {
students.remove(student.getRollNo());
System.out.println("Student: Roll No "
+ student.getRollNo() +", deleted from database");
}

//retrive list of students from the database


public List<StudentVO> getAllStudents() {
return students;
}

public StudentVO getStudent(int rollNo) {


return students.get(rollNo);
}

public void updateStudent(StudentVO student) {

students.get(student.getRollNo()).setName(student.getName());
System.out.println("Student: Roll No "
+ student.getRollNo() +", updated in the database");
}
}

Paso 3
Use StudentBO para demostrar el patrón de diseño de transferencia de
objetos.
TransferObjectPatternDemo.java
public class TransferObjectPatternDemo {
public static void main(String[] args) {
StudentBO studentBusinessObject = new StudentBO();

//print all students


for (StudentVO student :
studentBusinessObject.getAllStudents()) {
System.out.println("Student: [RollNo : "
+student.getRollNo()+", Name : "+student.getName()+"
]");
}

//update student
StudentVO student
=studentBusinessObject.getAllStudents().get(0);
student.setName("Michael");
studentBusinessObject.updateStudent(student);

//get the student


studentBusinessObject.getStudent(0);
System.out.println("Student: [RollNo : "
+student.getRollNo()+", Name : "+student.getName()+"
]");
}
}

Etapa 4
Verifique la salida.
Estudiante: [Rollo No: 0, Nombre: Robert]
Estudiante: [Rollo No: 1, Nombre: John]
Estudiante: Roll No 0, actualizado en la base de datos
Estudiante: [Número de rollo: 0, Nombre: Michael]

También podría gustarte