Design Pattern

Contenido Patrones de diseño - Inicio Patrones de diseño: descripción general Patrones de diseño - Patrón de fábrica Pat

Views 329 Downloads 1 File size 2MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

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

1

Patrones de creación Estos patrones de diseño proporcionan una forma de crear objetos mientras se oculta la 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.

2

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

3

Patrones de comportamiento 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 Inside Inside Inside

Rectangle::draw() method. Square::draw() method. RoundedRectangle::draw() method. 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 constructor como privado y tiene una instancia estática de sí mismo.

su

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 proporcionando funcionalidades predeterminadas.

interfaz

del

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

elemento

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 items = new ArrayList(); 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 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;

utilizará

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 shapeMap = new Hashtable(); 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 implementan la interfaz AdvancedMediaPlayer . reproducir archivos en formato vlc y mp4.

clases concretas que Estas clases pueden

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", audioPlayer.play("mp4", audioPlayer.play("vlc", audioPlayer.play("avi",

"beyond the horizon.mp3"); "alone.mp4"); "far far away.vlc"); "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 meetCriteria(List 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 meetCriteria(List persons) {

List malePersons = new ArrayList(); 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 meetCriteria(List persons) { List femalePersons = new ArrayList(); 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 meetCriteria(List persons) { List singlePersons = new ArrayList(); 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 meetCriteria(List persons) { List 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 meetCriteria(List persons) { List firstCriteriaItems = criteria.meetCriteria(persons); List 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 persons = new ArrayList(); persons.add(new persons.add(new persons.add(new persons.add(new persons.add(new persons.add(new Criteria Criteria Criteria Criteria Criteria female);

Person("Robert","Male", "Single")); Person("John","Male", "Married")); Person("Laura","Female", "Married")); Person("Diana","Female", "Single")); Person("Mike","Male", "Single")); Person("Bobby","Male", "Single"));

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

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 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: Soltero] Persona: Casado] Persona: Soltero] Persona: Soltero]

[Nombre: Robert, Sexo: Masculino, Estado civil: [Nombre: John, Sexo: Masculino, Estado civil: [Nombre: Mike, Sexo: Masculino, Estado civil: [Nombre: Bobby, Sexo: Masculino, Estado civil:

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 Persona: Soltero] Persona: Soltero] Persona: Soltero] Persona: Soltero] Persona: Casado]

o hembras: [Nombre: Robert, Sexo: Masculino, Estado civil: [Nombre: Diana, Sexo: Femenino, Estado civil: [Nombre: Mike, Sexo: Masculino, Estado civil: [Nombre: Bobby, Sexo: Masculino, Estado civil: [Nombre: Laura, Sexo: Femenino, Estado civil:

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 subordinates; // constructor public Employee(String name,String dept, int sal) { this.name = name; this.dept = dept; this.salary = sal; subordinates = new ArrayList(); } public void add(Employee e) { subordinates.add(e);

} public void remove(Employee e) { subordinates.remove(e); } public List 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: Empleado: [Nombre: salario: 20000] Empleado: [Nombre: 10000] Empleado: [Nombre: Empleado: [Nombre: salario: 20000] Empleado: [Nombre: 10000] Empleado: [Nombre: 10000]

John, departamento: CEO, salario: 30000] Robert, departamento: Jefe de ventas, Richard, departamento: Ventas, salario: Rob, departamento: Ventas, salario: 10000] Michel, departamento: Jefe de marketing, Laura, departamento: Marketing, salario: Bob, departamento: Marketing, salario:

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 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 {

demostración

@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 Círculo: Draw Crear círculo Círculo: Draw Crear círculo Círculo: Draw Crear círculo Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Crear círculo Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw Círculo: Draw

de () de () de () de () () () () de () () () () () () () () () () () () ()

color: negro [Color: negro, x: 36, y: 71, radio: 100 color: verde [Color: Verde, x: 27, y: 27, radio: 100 color: blanco [Color: Blanco, x: 64, y: 10, radio: 100 color: rojo [Color: Rojo, x: 15, y: 44, radio: 100 [Color: Verde, x: 19, y: 10, radio: 100 [Color: Verde, x: 94, y: 32, radio: 100 [Color: Blanco, x: 69, y: 98, radio: 100 color: azul [Color: Azul, x: 13, y: 4, radio: 100 [Color: Verde, x: 21, y: 21, radio: 100 [Color: Azul, x: 55, y: 86, radio: 100 [Color: Blanco, x: 90, y: 70, radio: 100 [Color: Verde, x: 78, y: 3, radio: 100 [Color: Verde, x: 64, y: 89, radio: 100 [Color: Azul, x: 3, y: 91, radio: 100 [Color: Azul, x: 62, y: 82, radio: 100 [Color: Verde, x: 97, y: 61, radio: 100 [Color: Verde, x: 86, y: 12, radio: 100 [Color: Verde, x: 38, y: 93, radio: 100 [Color: Rojo, x: 76, y: 82, radio: 100 [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