Guida rapida per Design Pattern
I modelli di progettazione rappresentano le migliori pratiche utilizzate dagli sviluppatori di software orientati agli oggetti esperti. I modelli di progettazione sono soluzioni a problemi generali che gli sviluppatori di software hanno dovuto affrontare durante lo sviluppo del software. Queste soluzioni sono state ottenute per tentativi ed errori da numerosi sviluppatori di software per un periodo di tempo piuttosto considerevole.
Cos'è Gang of Four (GOF)?
Nel 1994, quattro autori Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides hanno pubblicato un libro intitolato Design Patterns - Elements of Reusable Object-Oriented Software che ha avviato il concetto di Design Pattern nello sviluppo del software.
Questi autori sono noti collettivamente come Gang of Four (GOF). Secondo questi autori, i modelli di progettazione si basano principalmente sui seguenti principi di progettazione orientata agli oggetti.
Programma su un'interfaccia, non su un'implementazione
Preferisci la composizione degli oggetti all'ereditarietà
Utilizzo di Design Pattern
I Design Pattern hanno due utilizzi principali nello sviluppo del software.
Piattaforma comune per gli sviluppatori
I modelli di progettazione forniscono una terminologia standard e sono specifici per uno scenario particolare. Ad esempio, un modello di progettazione singleton indica l'uso di un singolo oggetto in modo che tutti gli sviluppatori che hanno familiarità con un modello di progettazione singolo utilizzino un singolo oggetto e possano dirsi l'un l'altro che il programma sta seguendo un modello singleton.
Migliori pratiche
I modelli di progettazione si sono evoluti nel corso di un lungo periodo di tempo e forniscono le migliori soluzioni a determinati problemi affrontati durante lo sviluppo del software. L'apprendimento di questi modelli aiuta gli sviluppatori inesperti ad apprendere la progettazione del software in modo facile e veloce.
Tipi di design pattern
Come da manuale di riferimento del modello di progettazione Design Patterns - Elements of Reusable Object-Oriented Software, ci sono 23 modelli di design. Questi modelli possono essere classificati in tre categorie: modelli creazionali, strutturali e comportamentali. Discuteremo anche un'altra categoria di design pattern: i design pattern J2EE.
SN | Modello e descrizione |
---|---|
1 | Creational Patterns Questi modelli di progettazione forniscono il modo per creare oggetti nascondendo la logica di creazione, piuttosto che istanziare gli oggetti direttamente utilizzando un nuovo operatore. Ciò fornisce al programma una maggiore flessibilità nel decidere quali oggetti devono essere creati per un determinato caso d'uso. |
2 | Structural Patterns Questi modelli di progettazione riguardano la composizione della classe e dell'oggetto. Il concetto di ereditarietà viene utilizzato per comporre interfacce e definire modi per comporre oggetti per ottenere nuove funzionalità. |
3 | Behavioral Patterns Questi modelli di progettazione riguardano specificamente la comunicazione tra gli oggetti. |
4 | J2EE Patterns Questi modelli di progettazione riguardano specificamente il livello di presentazione. Questi modelli vengono identificati da Sun Java Center. |
Factory pattern è uno dei design pattern più utilizzati in Java. Questo tipo di modello di progettazione rientra nel modello di creazione poiché questo modello fornisce uno dei modi migliori per creare un oggetto.
In Factory pattern, creiamo oggetti senza esporre la logica di creazione al client e ci riferiamo a oggetti appena creati utilizzando un'interfaccia comune.
Implementazione
Creeremo un'interfaccia Shape e classi concrete che implementano l' interfaccia Shape . Una ShapeFactory di classe factory viene definita come passaggio successivo.
FactoryPatternDemo , la nostra classe demo utilizzerà ShapeFactory per ottenere un oggetto Shape . Passerà le informazioni ( CIRCLE / RECTANGLE / SQUARE ) a ShapeFactory per ottenere il tipo di oggetto di cui ha bisogno.
Passo 1
Crea un'interfaccia.
Shape.java
public interface Shape {
void draw();
}
Passo 2
Crea classi concrete che implementano la stessa interfaccia.
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.");
}
}
Passaggio 3
Creare una Factory per generare un oggetto di classe concreta in base alle informazioni fornite.
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;
}
}
Passaggio 4
Utilizzare Factory per ottenere l'oggetto della classe concreta passando un'informazione come 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();
}
}
Passaggio 5
Verifica l'output.
Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.
I modelli di fabbrica astratti funzionano attorno a una super fabbrica che crea altre fabbriche. Questa fabbrica è anche chiamata fabbrica di fabbriche. Questo tipo di modello di progettazione rientra nel modello di creazione poiché questo modello fornisce uno dei modi migliori per creare un oggetto.
In Abstract Factory pattern un'interfaccia è responsabile della creazione di una factory di oggetti correlati senza specificare esplicitamente le loro classi. Ogni factory generata può fornire gli oggetti secondo il pattern Factory.
Implementazione
Creeremo un'interfaccia Shape e una classe concreta che la implementa. Creiamo una classe di fabbrica astratta AbstractFactory come passaggio successivo. Viene definita la classe Factory ShapeFactory, che estende AbstractFactory. Viene creata una classe di creatore / generatore di fabbrica FactoryProducer.
AbstractFactoryPatternDemo, la nostra classe demo utilizza FactoryProducer per ottenere un oggetto AbstractFactory. Passerà le informazioni (CIRCLE / RECTANGLE / SQUARE per Shape) ad AbstractFactory per ottenere il tipo di oggetto di cui ha bisogno.
Passo 1
Crea un'interfaccia per Shapes.
Shape.java
public interface Shape {
void draw();
}
Passo 2
Crea classi concrete che implementano la stessa interfaccia.
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.");
}
}
Passaggio 3
Crea una classe astratta per ottenere fabbriche per oggetti di forma normale e arrotondata.
AbstractFactory.java
public abstract class AbstractFactory {
abstract Shape getShape(String shapeType) ;
}
Passaggio 4
Crea classi Factory che estendono AbstractFactory per generare oggetti di classi concrete in base alle informazioni fornite.
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;
}
}
Passaggio 5
Creare una classe di generatore / produttore di fabbrica per ottenere le fabbriche passando un'informazione come Forma
FactoryProducer.java
public class FactoryProducer {
public static AbstractFactory getFactory(boolean rounded){
if(rounded){
return new RoundedShapeFactory();
}else{
return new ShapeFactory();
}
}
}
Passaggio 6
Utilizzare FactoryProducer per ottenere AbstractFactory al fine di ottenere fabbriche di classi concrete passando un'informazione come tipo.
AbstractFactoryPatternDemo.java
public class AbstractFactoryPatternDemo {
public static void main(String[] args) {
//get shape factory
AbstractFactory shapeFactory = FactoryProducer.getFactory(false);
//get an object of Shape Rectangle
Shape shape1 = shapeFactory.getShape("RECTANGLE");
//call draw method of Shape Rectangle
shape1.draw();
//get an object of Shape Square
Shape shape2 = shapeFactory.getShape("SQUARE");
//call draw method of Shape Square
shape2.draw();
//get 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();
}
}
Passaggio 7
Verifica l'output.
Inside Rectangle::draw() method.
Inside Square::draw() method.
Inside RoundedRectangle::draw() method.
Inside RoundedSquare::draw() method.
Il modello Singleton è uno dei modelli di progettazione più semplici in Java. Questo tipo di modello di progettazione rientra nel modello di creazione poiché questo modello fornisce uno dei modi migliori per creare un oggetto.
Questo modello coinvolge una singola classe che è responsabile della creazione del proprio oggetto assicurandosi che venga creato solo un singolo oggetto. Questa classe fornisce un modo per accedere al suo unico oggetto a cui è possibile accedere direttamente senza bisogno di istanziare l'oggetto della classe.
Implementazione
Creeremo una classe SingleObject . La classe SingleObject ha il suo costruttore come privato e ha un'istanza statica di se stessa.
La classe SingleObject fornisce un metodo statico per ottenere la sua istanza statica nel mondo esterno. SingletonPatternDemo , la nostra classe demo utilizzerà la classe SingleObject per ottenere un oggetto SingleObject .
Passo 1
Crea una classe 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!");
}
}
Passo 2
Ottieni l'unico oggetto dalla classe 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();
}
}
Passaggio 3
Verifica l'output.
Hello World!
Il modello Builder costruisce un oggetto complesso utilizzando oggetti semplici e utilizzando un approccio graduale. Questo tipo di modello di progettazione rientra nel modello di creazione poiché questo modello fornisce uno dei modi migliori per creare un oggetto.
Una classe Builder costruisce l'oggetto finale passo dopo passo. Questo builder è indipendente da altri oggetti.
Implementazione
Abbiamo considerato un caso aziendale di fast-food dove un pasto tipico potrebbe essere un hamburger e una bevanda fredda. Burger può essere sia un hamburger vegetariano che un hamburger di pollo e sarà confezionato da un involucro. La bevanda fredda potrebbe essere una coca cola o una pepsi e sarà confezionata in una bottiglia.
Creeremo un'interfaccia Item che rappresenta prodotti alimentari come hamburger e bevande fredde e classi concrete che implementano l' interfaccia Item e un'interfaccia Packing che rappresenta l'imballaggio di prodotti alimentari e classi concrete che implementano l' interfaccia Packing poiché l'hamburger verrebbe confezionato in involucro e freddo la bevanda sarebbe confezionata come una bottiglia.
Quindi creiamo una classe Meal con ArrayList of Item e un MealBuilder per costruire diversi tipi di oggetti Meal combinando Item . BuilderPatternDemo , la nostra classe demo utilizzerà MealBuilder per creare un pasto .
Passo 1
Creare un'interfaccia Item che rappresenti il cibo e l'imballaggio.
Item.java
public interface Item {
public String name();
public Packing packing();
public float price();
}
Packing.java
public interface Packing {
public String pack();
}
Passo 2
Crea classi concreate che implementano l'interfaccia di Packing.
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";
}
}
Passaggio 3
Crea classi astratte che implementano l'interfaccia dell'elemento fornendo funzionalità predefinite.
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();
}
Passaggio 4
Crea classi concrete che estendono le classi Burger e 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";
}
}
Coke.java
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";
}
}
Passaggio 5
Crea una classe Meal con oggetti Item definiti sopra.
Pasto.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());
}
}
}
Passaggio 6
Creare una classe MealBuilder, la vera classe builder responsabile della creazione di oggetti 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;
}
}
Passaggio 7
BuiderPatternDemo usa MealBuider per dimostrare il modello del generatore.
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());
}
}
Passaggio 8
Verifica l'output.
Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0
Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5
Il modello prototipo si riferisce alla creazione di oggetti duplicati tenendo a mente le prestazioni. Questo tipo di modello di progettazione rientra nel modello di creazione poiché questo modello fornisce uno dei modi migliori per creare un oggetto.
Questo modello implica l'implementazione di un'interfaccia prototipo che dice di creare un clone dell'oggetto corrente. Questo modello viene utilizzato quando la creazione di un oggetto direttamente è costosa. Ad esempio, un oggetto deve essere creato dopo una costosa operazione di database. Possiamo memorizzare nella cache l'oggetto, restituire il suo clone alla richiesta successiva e aggiornare il database come e quando necessario riducendo così le chiamate al database.
Implementazione
Creeremo una classe astratta Shape e classi concrete che estendono la classe Shape . Una classe ShapeCache è definita come un passaggio successivo che memorizza gli oggetti forma in un Hashtable e restituisce il loro clone quando richiesto.
PrototypPatternDemo , la nostra classe demo utilizzerà la classe ShapeCache per ottenere un oggetto Shape .
Passo 1
Crea una classe astratta che implementa l' interfaccia 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;
}
}
Passo 2
Crea classi concrete che estendono la classe precedente.
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.");
}
}
Passaggio 3
Crea una classe per ottenere classi concreate dal database e memorizzarle in un Hashtable .
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);
}
}
Passaggio 4
PrototypePatternDemo usa la classe ShapeCache per ottenere cloni di forme archiviate in un Hashtable .
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());
}
}
Passaggio 5
Verifica l'output.
Shape : Circle
Shape : Square
Shape : Rectangle
Il modello dell'adattatore funziona come un ponte tra due interfacce incompatibili. Questo tipo di modello di progettazione rientra nel modello strutturale poiché questo modello combina la capacità di due interfacce indipendenti.
Questo modello coinvolge una singola classe che è responsabile di unire funzionalità di interfacce indipendenti o incompatibili. Un esempio di vita reale potrebbe essere un caso di lettore di schede che funge da adattatore tra la scheda di memoria e un laptop. Si collega la scheda di memoria al lettore di schede e il lettore di schede al laptop in modo che la scheda di memoria possa essere letta tramite laptop.
Stiamo dimostrando l'uso del pattern Adapter tramite il seguente esempio in cui un dispositivo lettore audio può riprodurre solo file mp3 e desidera utilizzare un lettore audio avanzato in grado di riprodurre file vlc e mp4.
Implementazione
Abbiamo un'interfaccia MediaPlayer e una classe concreta AudioPlayer che implementa l' interfaccia MediaPlayer . AudioPlayer può riprodurre file audio in formato mp3 per impostazione predefinita.
Abbiamo un'altra interfaccia AdvancedMediaPlayer e classi concrete che implementano l' interfaccia AdvancedMediaPlayer. Queste classi possono riprodurre file in formato vlc e mp4.
Vogliamo fare in modo che AudioPlayer riproduca anche altri formati. Per ottenere ciò, abbiamo creato una classe adattatore MediaAdapter che implementa l' interfaccia MediaPlayer e utilizza oggetti AdvancedMediaPlayer per riprodurre il formato richiesto.
AudioPlayer utilizza la classe dell'adattatore MediaAdapter passandogli il tipo di audio desiderato senza conoscere la classe effettiva che può riprodurre il formato desiderato. AdapterPatternDemo , la nostra classe demo utilizzerà la classe AudioPlayer per riprodurre vari formati.
Passo 1
Crea interfacce per Media Player e 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);
}
Passo 2
Crea classi concrete che implementano l' interfaccia 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);
}
}
Passaggio 3
Crea una classe adattatore che implementa l' interfaccia 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);
}
}
}
Passaggio 4
Crea una classe concreta che implementa l' interfaccia 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");
}
}
}
Passaggio 5
Usa AudioPlayer per riprodurre diversi tipi di formati 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");
}
}
Passaggio 6
Verifica l'output.
Playing mp3 file. Name: beyond the horizon.mp3
Playing mp4 file. Name: alone.mp4
Playing vlc file. Name: far far away.vlc
Invalid media. avi format not supported
Bridge viene utilizzato quando è necessario disaccoppiare un'astrazione dalla sua implementazione in modo che le due possano variare indipendentemente. Questo tipo di modello di progettazione rientra nel modello strutturale poiché questo modello disaccoppia la classe di implementazione e la classe astratta fornendo una struttura a ponte tra di loro.
Questo modello coinvolge un'interfaccia che funge da ponte che rende la funzionalità delle classi concrete indipendenti dalle classi dell'implementazione dell'interfaccia. Entrambi i tipi di classi possono essere modificati strutturalmente senza influenzarsi a vicenda.
Stiamo dimostrando l'uso del pattern Bridge tramite il seguente esempio in cui un cerchio può essere disegnato in diversi colori usando lo stesso metodo di classe astratta ma diverse classi di implementazione del bridge.
Implementazione
Abbiamo un'interfaccia DrawAPI che funge da implementatore di bridge e classi concrete RedCircle , GreenCircle che implementano l' interfaccia DrawAPI . Shape è una classe astratta e utilizzerà l'oggetto DrawAPI . BridgePatternDemo , la nostra classe demo utilizzerà la classe Shape per disegnare cerchi colorati diversi.
Passo 1
Crea l'interfaccia per l'implementazione del bridge.
DrawAPI.java
public interface DrawAPI {
public void drawCircle(int radius, int x, int y);
}
Passo 2
Creare classi di implementazione di ponti in cemento che implementano l' interfaccia 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 +"]");
}
}
Passaggio 3
Creare una forma di classe astratta utilizzando l' interfaccia DrawAPI .
Shape.java
public abstract class Shape {
protected DrawAPI drawAPI;
protected Shape(DrawAPI drawAPI){
this.drawAPI = drawAPI;
}
public abstract void draw();
}
Passaggio 4
Crea una classe concreta che implementa l' interfaccia 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);
}
}
Passaggio 5
Usa le classi Shape e DrawAPI per disegnare cerchi colorati diversi.
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();
}
}
Passaggio 6
Verifica l'output.
Drawing Circle[ color: red, radius: 10, x: 100, 100]
Drawing Circle[ color: green, radius: 10, x: 100, 100]
Il modello di filtro o modello di criteri è un modello di progettazione che consente agli sviluppatori di filtrare un set di oggetti, utilizzando criteri diversi, concatenandoli in modo disaccoppiato tramite operazioni logiche. Questo tipo di modello di progettazione rientra nel modello strutturale poiché questo modello combina più criteri per ottenere criteri singoli.
Implementazione
Creeremo un oggetto Person , un'interfaccia Criteria e classi concrete che implementano questa interfaccia per filtrare l'elenco degli oggetti Person . CriteriaPatternDemo , la nostra classe demo utilizza oggetti Criteria per filtrare gli oggetti Elenco di persone in base a vari criteri e alle loro combinazioni.
Passo 1
Creare una classe su cui applicare i criteri.
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;
}
}
Passo 2
Crea un'interfaccia per Criteria.
Criteria.java
import java.util.List;
public interface Criteria {
public List<Person> meetCriteria(List<Person> persons);
}
Passaggio 3
Crea classi concrete che implementano l' interfaccia 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;
}
}
Step4
Usa criteri diversi e la loro combinazione per filtrare le persone.
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()
+" ]");
}
}
}
Passaggio 5
Verifica l'output.
Males:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : John, Gender : Male, Marital Status : Married ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]
Females:
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]
Single Males:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]
Single Or Females:
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
Il pattern composito viene utilizzato quando è necessario trattare un gruppo di oggetti in modo simile come un singolo oggetto. Il modello composito compone gli oggetti in termini di una struttura ad albero per rappresentare una parte così come l'intera gerarchia. Questo tipo di modello di progettazione rientra nel modello strutturale poiché questo modello crea una struttura ad albero di un gruppo di oggetti.
Questo modello crea una classe contenente un gruppo dei propri oggetti. Questa classe fornisce modi per modificare il proprio gruppo di stessi oggetti.
Stiamo dimostrando l'uso del pattern Composite tramite il seguente esempio in cui mostra la gerarchia dei dipendenti di un'organizzazione.
Implementazione
Abbiamo una classe Employee che funge da classe di attori del modello composito. CompositePatternDemo , la nostra classe demo utilizzerà la classe Employee per aggiungere la gerarchia a livello di reparto e stampare tutti i dipendenti.
Passo 1
Crea una classe Employee con un elenco di oggetti Employee .
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+" ]");
}
}
Passo 2
Utilizzare la classe Employee per creare e stampare la gerarchia dei dipendenti.
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);
}
}
}
}
Passaggio 3
Verifica l'output.
Employee :[ Name : John, dept : CEO, salary :30000 ]
Employee :[ Name : Robert, dept : Head Sales, salary :20000 ]
Employee :[ Name : Richard, dept : Sales, salary :10000 ]
Employee :[ Name : Rob, dept : Sales, salary :10000 ]
Employee :[ Name : Michel, dept : Head Marketing, salary :20000 ]
Employee :[ Name : Laura, dept : Marketing, salary :10000 ]
Employee :[ Name : Bob, dept : Marketing, salary :10000 ]
Il motivo Decorator permette di aggiungere nuove funzionalità ad un oggetto esistente senza alterarne la struttura. Questo tipo di modello di progettazione rientra nel modello strutturale poiché questo modello funge da involucro per la classe esistente.
Questo modello crea una classe decoratore che avvolge la classe originale e fornisce funzionalità aggiuntive mantenendo intatta la firma dei metodi di classe.
Stiamo dimostrando l'uso del motivo Decorator tramite il seguente esempio in cui decoreremo una forma con un po 'di colore senza alterare la classe della forma.
Implementazione
Creeremo un'interfaccia Shape e classi concrete che implementano l' interfaccia Shape . Creiamo quindi una classe di decoratore astratta ShapeDecorator che implementa l' interfaccia Shape e ha l' oggetto Shape come variabile di istanza.
RedShapeDecorator è una classe concreta che implementa ShapeDecorator .
DecoratorPatternDemo , la nostra classe demo utilizzerà RedShapeDecorator per decorare gli oggetti Shape .
Passo 1
Crea un'interfaccia.
Shape.java
public interface Shape {
void draw();
}
Passo 2
Crea classi concrete che implementano la stessa interfaccia.
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");
}
}
Passaggio 3
Crea una classe decoratore astratta che implementa l' interfaccia Shape .
ShapeDecorator.java
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape){
this.decoratedShape = decoratedShape;
}
public void draw(){
decoratedShape.draw();
}
}
Passaggio 4
Crea una classe decoratore in cemento estendendo la classe 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");
}
}
Passaggio 5
Usa il RedShapeDecorator per decorare gli oggetti 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();
}
}
Passaggio 6
Verifica l'output.
Circle with normal border
Shape: Circle
Circle of red border
Shape: Circle
Border Color: Red
Rectangle of red border
Shape: Rectangle
Border Color: Red
Il motivo della facciata nasconde le complessità del sistema e fornisce un'interfaccia al cliente tramite la quale il cliente può accedere al sistema. Questo tipo di modello di progettazione rientra nel modello strutturale poiché questo modello aggiunge un'interfaccia al sistema in uscita per nascondere le sue complessità.
Questo modello coinvolge una singola classe che fornisce metodi semplificati richiesti dal client e delega le chiamate ai metodi delle classi di sistema esistenti.
Implementazione
Creeremo un'interfaccia Shape e classi concrete che implementano l' interfaccia Shape . Una classe di facciata ShapeMaker viene definita come passaggio successivo.
La classe ShapeMaker utilizza le classi concrete per delegare le chiamate utente a queste classi. FacadePatternDemo , la nostra classe demo utilizzerà la classe ShapeMaker per mostrare i risultati.
Passo 1
Crea un'interfaccia.
Shape.java
public interface Shape {
void draw();
}
Passo 2
Crea classi concrete che implementano la stessa interfaccia.
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()");
}
}
Passaggio 3
Crea una lezione di facciata.
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();
}
}
Passaggio 4
Usa la facciata per disegnare vari tipi di forme.
FacadePatternDemo.java
public class FacadePatternDemo {
public static void main(String[] args) {
ShapeMaker shapeMaker = new ShapeMaker();
shapeMaker.drawCircle();
shapeMaker.drawRectangle();
shapeMaker.drawSquare();
}
}
Passaggio 5
Verifica l'output.
Circle::draw()
Rectangle::draw()
Square::draw()
Il modello Flyweight viene utilizzato principalmente per ridurre il numero di oggetti creati, per ridurre l'ingombro della memoria e aumentare le prestazioni. Questo tipo di modello di progettazione rientra nel modello strutturale in quanto fornisce modi per ridurre il numero di oggetti migliorando così la struttura degli oggetti richiesti dall'applicazione.
Il modello Flyweight tenta di riutilizzare oggetti simili già esistenti memorizzandoli e crea un nuovo oggetto quando non viene trovato alcun oggetto corrispondente. Dimostreremo questo modello disegnando 20 cerchi di posizioni diverse ma creeremo solo 5 oggetti. Sono disponibili solo 5 colori, quindi la proprietà del colore viene utilizzata per controllare gli oggetti Circle già esistenti .
Implementazione
Creeremo un'interfaccia Shape e una classe concreta Circle che implementa l' interfaccia Shape . Una ShapeFactory di classe factory viene definita come passaggio successivo.
ShapeFactory ha una HashMap di Circle avente la chiave come colore dell'oggetto Circle . Ogni volta che arriva una richiesta di creare un cerchio di un colore particolare a ShapeFactory . ShapeFactory controlla l'oggetto circle nella sua HashMap , se l'oggetto di Circle viene trovato, quell'oggetto viene restituito altrimenti viene creato un nuovo oggetto, memorizzato in hashmap per un uso futuro e restituito al client.
FlyWeightPatternDemo , la nostra classe demo utilizzerà ShapeFactory per ottenere un oggetto Shape . Passerà le informazioni ( rosso / verde / blu / nero / bianco ) a ShapeFactory per ottenere il cerchio del colore desiderato di cui ha bisogno.
Passo 1
Crea un'interfaccia.
Shape.java
public interface Shape {
void draw();
}
Passo 2
Crea una classe concreta che implementa la stessa interfaccia.
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);
}
}
Passaggio 3
Creare una Factory per generare un oggetto di classe concreta in base alle informazioni fornite.
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;
}
}
Passaggio 4
Usa Factory per ottenere l'oggetto della classe concreta passando un'informazione come il colore.
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);
}
}
Passaggio 5
Verifica l'output.
Creating circle of color : Black
Circle: Draw() [Color : Black, x : 36, y :71, radius :100
Creating circle of color : Green
Circle: Draw() [Color : Green, x : 27, y :27, radius :100
Creating circle of color : White
Circle: Draw() [Color : White, x : 64, y :10, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 15, y :44, radius :100
Circle: Draw() [Color : Green, x : 19, y :10, radius :100
Circle: Draw() [Color : Green, x : 94, y :32, radius :100
Circle: Draw() [Color : White, x : 69, y :98, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 13, y :4, radius :100
Circle: Draw() [Color : Green, x : 21, y :21, radius :100
Circle: Draw() [Color : Blue, x : 55, y :86, radius :100
Circle: Draw() [Color : White, x : 90, y :70, radius :100
Circle: Draw() [Color : Green, x : 78, y :3, radius :100
Circle: Draw() [Color : Green, x : 64, y :89, radius :100
Circle: Draw() [Color : Blue, x : 3, y :91, radius :100
Circle: Draw() [Color : Blue, x : 62, y :82, radius :100
Circle: Draw() [Color : Green, x : 97, y :61, radius :100
Circle: Draw() [Color : Green, x : 86, y :12, radius :100
Circle: Draw() [Color : Green, x : 38, y :93, radius :100
Circle: Draw() [Color : Red, x : 76, y :82, radius :100
Circle: Draw() [Color : Blue, x : 95, y :82, radius :100
In Proxy pattern, una classe rappresenta la funzionalità di un'altra classe. Questo tipo di modello di progettazione rientra nel modello strutturale.
In Proxy pattern, creiamo un oggetto con un oggetto originale per interfacciare la sua funzionalità al mondo esterno.
Implementazione
Creeremo un'interfaccia Image e classi concrete che implementano l' interfaccia Image . ProxyImage è una classe proxy per ridurre il footprint di memoria del caricamento di oggetti RealImage .
ProxyPatternDemo , la nostra classe demo utilizzerà ProxyImage per ottenere un oggetto Image da caricare e visualizzare come necessario.
Passo 1
Crea un'interfaccia.
Image.java
public interface Image {
void display();
}
Passo 2
Crea classi concrete che implementano la stessa interfaccia.
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();
}
}
Passaggio 3
Utilizzare ProxyImage per ottenere l'oggetto della classe RealImage quando richiesto.
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();
}
}
Passaggio 4
Verifica l'output.
Loading test_10mb.jpg
Displaying test_10mb.jpg
Displaying test_10mb.jpg
Come suggerisce il nome, il modello della catena di responsabilità crea una catena di oggetti riceventi per una richiesta. Questo modello disaccoppia mittente e destinatario di una richiesta in base al tipo di richiesta. Questo modello rientra nei modelli comportamentali.
In questo schema, normalmente ogni ricevitore contiene un riferimento a un altro ricevitore. Se un oggetto non è in grado di gestire la richiesta, passa la stessa al destinatario successivo e così via.
Implementazione
Abbiamo creato una classe astratta AbstractLogger con un livello di registrazione. Quindi abbiamo creato tre tipi di logger che estendono l' AbstractLogger . Ogni logger controlla il livello del messaggio al suo livello e stampa di conseguenza altrimenti non stampa e passa il messaggio al suo logger successivo.
Passo 1
Crea una classe logger astratta.
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);
}
Passo 2
Crea classi concrete che estendono il logger.
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);
}
}
Passaggio 3
Crea diversi tipi di logger. Assegna loro i livelli di errore e imposta il logger successivo in ogni logger. Il logger successivo in ogni logger rappresenta la parte della catena.
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.");
}
}
Passaggio 4
Verifica l'output.
Standard Console::Logger: This is an information.
File::Logger: This is an debug level information.
Standard Console::Logger: This is an debug level information.
Error Console::Logger: This is an error information.
File::Logger: This is an error information.
Standard Console::Logger: This is an error information.
Il modello di comando è un modello di progettazione basato sui dati e rientra nella categoria dei modelli comportamentali. Una richiesta viene racchiusa in un oggetto come comando e passata all'oggetto invoker. L'oggetto Invoker cerca l'oggetto appropriato che può gestire questo comando e passare il comando all'oggetto corrispondente e quell'oggetto esegue il comando.
Implementazione
Abbiamo creato un'interfaccia Order che agisce come un comando. Abbiamo creato una classe Stock che funge da richiesta. Abbiamo classi di comando concrete BuyStock e SellStock che implementano l' interfaccia degli ordini che eseguirà l'effettiva elaborazione dei comandi. Viene creato un broker di classe che funge da oggetto invoker. Può prendere ordini ed effettuare ordini.
L' oggetto Broker utilizza il modello di comando per identificare quale oggetto eseguirà il comando in base al tipo di comando. CommandPatternDemo , la nostra classe demo utilizzerà la classe Broker per dimostrare il modello di comando.
Passo 1
Crea un'interfaccia di comando.
Order.java
public interface Order {
void execute();
}
Passo 2
Crea una classe di richiesta.
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");
}
}
Passaggio 3
Crea classi concrete che implementano l' interfaccia Order .
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();
}
}
Passaggio 4
Crea la classe di invoker del comando
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();
}
}
Passaggio 5
Usa la classe Broker per prendere ed eseguire comandi.
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();
}
}
Passaggio 6
Verifica l'output.
Stock [ Name: ABC, Quantity: 10 ] bought
Stock [ Name: ABC, Quantity: 10 ] sold
Il pattern interprete fornisce un modo per valutare la grammatica o l'espressione della lingua. Questo tipo di modello rientra nei modelli comportamentali. Questo modello implica l'implementazione di un'interfaccia di espressione che indica di interpretare un particolare contesto. Questo modello viene utilizzato nell'analisi SQL, nel motore di elaborazione dei simboli ecc.
Implementazione
Creeremo un'interfaccia Expression e classi concrete che implementano l' interfaccia Expression . Viene definita una classe TerminalExpression che funge da interprete principale del contesto in questione. Altre classi OrExpression , AndExpression vengono utilizzate per creare espressioni combinatorie.
InterpreterPatternDemo , la nostra classe demo utilizzerà la classe Expression per creare regole e dimostrare l'analisi delle espressioni.
Passo 1
Crea un'interfaccia di espressione.
Expression.java
public interface Expression {
public boolean interpret(String context);
}
Passo 2
Crea classi concrete che implementano l'interfaccia sopra.
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);
}
}
Passaggio 3
InterpreterPatternDemo utilizza la classe Expression per creare regole e quindi analizzarle.
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"));
}
}
Passaggio 4
Verifica l'output.
John is male? true
Julie is a married women? true
Il pattern Iterator è un design pattern molto comunemente usato negli ambienti di programmazione Java e .Net. Questo modello viene utilizzato per ottenere un modo per accedere agli elementi di un oggetto di raccolta in modo sequenziale senza alcuna necessità di conoscere la sua rappresentazione sottostante.
Il modello iteratore rientra nella categoria del modello comportamentale.
Implementazione
Creeremo un'interfaccia Iterator che narra il metodo di navigazione e un'interfaccia Container che riavvia l'iteratore. Le classi concrete che implementano l' interfaccia del contenitore saranno responsabili dell'implementazione dell'interfaccia di Iterator e del suo utilizzo
IteratorPatternDemo , la nostra classe demo utilizzerà NamesRepository , un'implementazione di una classe concreta per stampare un Names archiviato come raccolta in NamesRepository .
Passo 1
Crea interfacce.
Iterator.java
public interface Iterator {
public boolean hasNext();
public Object next();
}
Container.java
public interface Container {
public Iterator getIterator();
}
Passo 2
Crea una classe concreta che implementa l' interfaccia del contenitore . Questa classe ha la classe interna NameIterator che implementa l' interfaccia Iterator .
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;
}
}
}
Passaggio 3
Usa il NameRepository per ottenere l'iteratore e stampare i nomi.
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);
}
}
}
Passaggio 4
Verifica l'output.
Name : Robert
Name : John
Name : Julie
Name : Lora
Il modello mediatore viene utilizzato per ridurre la complessità della comunicazione tra più oggetti o classi. Questo modello fornisce una classe mediatore che normalmente gestisce tutte le comunicazioni tra classi diverse e supporta una facile manutenibilità del codice mediante accoppiamento libero. Il modello del mediatore rientra nella categoria del modello comportamentale.
Implementazione
Stiamo dimostrando il modello di mediatore con l'esempio di una chat room in cui più utenti possono inviare messaggi alla chat ed è responsabilità della chat room mostrare i messaggi a tutti gli utenti. Abbiamo creato due classi ChatRoom e User . Gli oggetti utente useranno il metodo ChatRoom per condividere i loro messaggi.
MediatorPatternDemo , la nostra classe demo utilizzerà gli oggetti utente per mostrare la comunicazione tra di loro.
Passo 1
Crea un corso di mediatore.
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);
}
}
Passo 2
Crea una classe utente
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);
}
}
Passaggio 3
Usa l' oggetto Utente per mostrare le comunicazioni tra di loro.
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!");
}
}
Passaggio 4
Verifica l'output.
Thu Jan 31 16:05:46 IST 2013 [Robert] : Hi! John!
Thu Jan 31 16:05:46 IST 2013 [John] : Hello! Robert!
Lo schema Memento viene utilizzato per ridurre il punto in cui si desidera ripristinare lo stato di un oggetto a uno stato precedente. Il modello ricordo rientra nella categoria dei modelli comportamentali.
Implementazione
Lo schema Memento utilizza tre classi di attori. Memento contiene lo stato di un oggetto da restaurare. Originator crea e memorizza gli stati negli oggetti Memento e nell'oggetto Caretaker che è responsabile del ripristino dello stato dell'oggetto da Memento. Abbiamo creato le classi Memento , Originator e CareTaker .
MementoPatternDemo , la nostra classe demo utilizzerà gli oggetti CareTaker e Originator per mostrare il ripristino degli stati degli oggetti.
Passo 1
Crea una classe Memento.
Memento.java
public class Memento {
private String state;
public Memento(String state){
this.state = state;
}
public String getState(){
return state;
}
}
Passo 2
Crea la classe Originator
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();
}
}
Passaggio 3
Crea una classe 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);
}
}
Passaggio 4
Usa gli oggetti CareTaker e 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());
}
}
Step 5
Verify the output.
Current State: State #4
First saved State: State #2
Second saved State: State #3
Observer pattern is used when there is one to many relationship between objects such as if one object is modified, its depenedent objects are to be notified automatically. Observer pattern falls under behavioral pattern category.
Implementation
Observer pattern uses three actor classes. Subject, Observer and Client. Subject, an object having methods to attach and de-attach observers to a client object. We've created classes Subject, Observer abstract class and concrete classes extending the abstract class the Observer.
ObserverPatternDemo, our demo class will use Subject and concrete class objects to show observer pattern in action.
Step 1
Create Subject class.
Subject.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();
}
}
}
Step 2
Create Observer class.
Observer.java
public abstract class Observer {
protected Subject subject;
public abstract void update();
}
Step 3
Create concrete observer classes
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() );
}
}
Step 4
Use Subject and concrete observer objects.
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);
}
}
Step 5
Verify the output.
First state change: 15
Hex String: F
Octal String: 17
Binary String: 1111
Second state change: 10
Hex String: A
Octal String: 12
Binary String: 1010
In State pattern a class behavior changes based on its state. This type of design pattern comes under behavior pattern.
In State pattern, we create objects which represent various states and a context object whose behavior varies as its state object changes.
Implementation
We're going to create a State interface defining a action and concrete state classes implementing the State interface. Context is a class which carries a State.
StaePatternDemo, our demo class will use Context and state objects to demonstrate change in Context behavior based on type of state it is in.
Step 1
Create an interface.
Image.java
public interface State {
public void doAction(Context context);
}
Step 2
Create concrete classes implementing the same interface.
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";
}
}
Step 3
Create Context Class.
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;
}
}
Step 4
Use the Context to see change in behaviour when State changes.
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());
}
}
Step 5
Verify the output.
Player is in start state
Start State
Player is in stop state
Stop State
In Null Object pattern, a null object replaces check of NULL object instance. Instead of putting if check for a null value, Null Object reflects a do nothing relationship. Such Null object can also be used to provide default behaviour in case data is not available.
In Null Object pattern, we create a abstract class specifying the various operations to be done, concreate classes extending this class and a null object class providing do nothing implemention of this class and will be used seemlessly where we need to check null value.
Implementation
We're going to create a AbstractCustomer abstract class defining opearations, here the name of the customer and concrete classes extending the AbstractCustomer class. A factory class CustomerFactory is created to return either RealCustomer or NullCustomer objects based on the name of customer passed to it.
NullPatternDemo, our demo class will use CustomerFactory to demonstrate use of Null Object pattern.
Step 1
Create an abstract class.
AbstractCustomer.java
public abstract class AbstractCustomer {
protected String name;
public abstract boolean isNil();
public abstract String getName();
}
Step 2
Create concrete classes extending the above class.
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;
}
}
Step 3
Create CustomerFactory Class.
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();
}
}
Step 4
Use the CustomerFactory get either RealCustomer or NullCustomer objects based on the name of customer passed to it.
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());
}
}
Step 5
Verify the output.
Customers
Rob
Not Available in Customer Database
Julie
Not Available in Customer Database
In Strategy pattern, a class behavior or its algorithm can be changed at run time. This type of design pattern comes under behavior pattern.
In Strategy pattern, we create objects which represent various strategies and a context object whose behavior varies as per its strategy object. The strategy object changes the executing algorithm of the context object.
Implementation
We're going to create a Strategy interface defining a action and concrete strategy classes implementing the Strategy interface. Context is a class which uses a Strategy.
StrategyPatternDemo, our demo class will use Context and strategy objects to demonstrate change in Context behaviour based on strategy it deploys or uses.
Step 1
Create an interface.
Strategy.java
public interface Strategy {
public int doOperation(int num1, int num2);
}
Step 2
Create concrete classes implementing the same interface.
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;
}
}
Step 3
Create Context Class.
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);
}
}
Step 4
Use the Context to see change in behaviour when it changes its Strategy.
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));
}
}
Step 5
Verify the output.
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
In Template pattern, an abstract class exposes defined way(s)/template(s) to execute its methods. Its subclasses can overrides the method implementations as per need basis but the invocation is to be in the same way as defined by an abstract class. This pattern comes under behavior pattern category.
Implementation
We're going to create a Game abstract class defining operations with a template method set to be final so that it cannot be overridden. Cricket and Football are concrete classes extend Game and override its methods.
TemplatePatternDemo, our demo class will use Game to demonstrate use of template pattern.
Step 1
Create an abstract class with a template method being 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();
}
}
Step 2
Create concrete classes extending the above class.
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!");
}
}
Step 3
Use the Game's template method play() to demonstrate a defined way of playing game.
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();
}
}
Step 4
Verify the output.
Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!
Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
In Visitor pattern, we use a visitor class which changes the executing algorithm of an element class. By this way, execution algorithm of element can varies as visitor varies. This pattern comes under behavior pattern category. As per the pattern, element object has to accept the visitor object so that visitor object handles the operation on the element object.
Implementation
We're going to create a ComputerPart interface defining accept opearation.Keyboard, Mouse, Monitor and Computer are concrete classes implementing ComputerPart interface. We'll define another interface ComputerPartVisitor which will define a visitor class operations. Computer uses concrete visitor to do corresponding action.
VisitorPatternDemo, our demo class will use Computer, ComputerPartVisitor classes to demonstrate use of visitor pattern.
Step 1
Define an interface to represent element.
ComputerPart.java
public interface class ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}
Step 2
Create concrete classes extending the above class.
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);
}
}
Passaggio 3
Definisci un'interfaccia per rappresentare il visitatore.
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);
}
Passaggio 4
Crea un visitatore concreto implementando la classe sopra.
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.");
}
}
Passaggio 5
Utilizzare ComputerPartDisplayVisitor per visualizzare parti di Computer .
VisitorPatternDemo.java
public class VisitorPatternDemo {
public static void main(String[] args) {
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
}
}
Passaggio 6
Verifica l'output.
Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.
Pattern MVC è l'acronimo di Model-View-Controller Pattern. Questo modello viene utilizzato per separare le preoccupazioni dell'applicazione.
Model- Il modello rappresenta un oggetto o un POJO JAVA che trasporta dati. Può anche avere una logica per aggiornare il controller se i suoi dati cambiano.
View - Visualizza rappresenta la visualizzazione dei dati contenuti nel modello.
Controller- Il controller agisce sia sul modello che sulla vista. Controlla il flusso di dati nell'oggetto del modello e aggiorna la vista ogni volta che i dati cambiano. Mantiene Vista e Modello separati.
Implementazione
Creeremo un oggetto Student che funge da modello. StudentView sarà una classe di visualizzazione che può stampare i dettagli degli studenti sulla console e StudentController è la classe controller responsabile dell'archiviazione dei dati nell'oggetto Student e dell'aggiornamento della visualizzazione StudentView di conseguenza.
MVCPatternDemo , la nostra classe demo utilizzerà StudentController per dimostrare l'uso del pattern MVC.
Passo 1
Crea modello.
Student.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;
}
}
Passo 2
Crea 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);
}
}
Passaggio 3
Crea controller.
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());
}
}
Passaggio 4
Utilizzare i metodi StudentController per dimostrare l'utilizzo del modello di progettazione 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;
}
}
Passaggio 5
Verifica l'output.
Student:
Name: Robert
Roll No: 10
Student:
Name: Julie
Roll No: 10
Il modello delegato aziendale viene utilizzato per separare il livello di presentazione e il livello aziendale. Fondamentalmente viene utilizzato per ridurre la comunicazione o la funzionalità di ricerca remota al codice di livello aziendale nel codice del livello di presentazione. Nel livello aziendale abbiamo seguito le entità.
Client - Il codice del livello di presentazione può essere JSP, servlet o codice java dell'interfaccia utente.
Business Delegate - Una singola classe di punto di ingresso per le entità client per fornire l'accesso ai metodi del servizio aziendale.
LookUp Service - L'oggetto del servizio di ricerca è responsabile di ottenere l'implementazione aziendale relativa e fornire l'accesso all'oggetto delegato aziendale.
Business Service- Interfaccia del servizio aziendale. Le classi concrete implementano questo servizio aziendale per fornire una logica di implementazione aziendale effettiva.
Implementazione
Creeremo un Client , BusinessDelegate , BusinessService , LookUpService , JMSService ed EJBService che rappresentano varie entità del pattern Business Delegate.
BusinessDelegatePatternDemo , la nostra classe demo utilizzerà BusinessDelegate e Client per dimostrare l'uso del pattern Business Delegate.
Passo 1
Crea interfaccia BusinessService.
BusinessService.java
public interface BusinessService {
public void doProcessing();
}
Passo 2
Crea classi di servizio concreate.
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");
}
}
Passaggio 3
Crea servizio di ricerca aziendale.
BusinessLookUp.java
public class BusinessLookUp {
public BusinessService getBusinessService(String serviceType){
if(serviceType.equalsIgnoreCase("EJB")){
return new EJBService();
}else {
return new JMSService();
}
}
}
Passaggio 4
Crea delegato aziendale.
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();
}
}
Passaggio 5
Crea cliente.
Student.java
public class Client {
BusinessDelegate businessService;
public Client(BusinessDelegate businessService){
this.businessService = businessService;
}
public void doTask(){
businessService.doTask();
}
}
Passaggio 6
Utilizzare le classi BusinessDelegate e Client per dimostrare il modello 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();
}
}
Passaggio 7
Verifica l'output.
Processing task by invoking EJB Service
Processing task by invoking JMS Service
Il modello di entità composita viene utilizzato nel meccanismo di persistenza EJB. Un'entità Composite è un bean di entità EJB che rappresenta un grafico di oggetti. Quando un'entità composita viene aggiornata, i bean di oggetti dipendenti internamente vengono aggiornati automaticamente come gestiti dal bean di entità EJB. Di seguito sono riportati i partecipanti a Composite Entity Bean.
Composite Entity - È un bean di entità primaria e può essere a grana grossa o può contenere un oggetto a grana grossa da utilizzare a scopo di persistenza.
Coarse-Grained Object-Questo oggetto contiene oggetti dipendenti. Ha un proprio ciclo di vita e gestisce anche il ciclo di vita degli oggetti dipendenti.
Dependent Object - Oggetti dipendenti è un oggetto che dipende da un oggetto a grana grossa per il suo ciclo di vita di persistenza.
Strategies - Strategies rappresenta come implementare un'entità composta.
Implementazione
Creeremo un oggetto CompositeEntity che funge da CompositeEntity. CoarseGrainedObject sarà una classe che contiene oggetti dipendenti. CompositeEntityPatternDemo , la nostra classe demo utilizzerà la classe Client per dimostrare l'uso del pattern di entità composite.
Passo 1
Crea oggetti dipendenti.
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;
}
}
Passo 2
Crea oggetto a grana grossa.
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()};
}
}
Passaggio 3
Crea entità composita.
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();
}
}
Passaggio 4
Crea la classe Client per utilizzare l'entità composita.
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);
}
}
Passaggio 5
Utilizzare il client per dimostrare l'utilizzo del modello di progettazione di entità composite.
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();
}
}
Passaggio 6
Verifica l'output.
Data: Test
Data: Data
Data: Second Test
Data: Data1
Il modello di oggetto di accesso ai dati o il modello DAO viene utilizzato per separare l'API o le operazioni di accesso ai dati di basso livello dai servizi aziendali di alto livello. Di seguito sono riportati i partecipanti a Data Access Object Pattern.
Data Access Object Interface - Questa interfaccia definisce le operazioni standard da eseguire su uno o più oggetti del modello.
Data Access Object concrete class-Questa classe implementa l'interfaccia sopra. Questa classe è responsabile per ottenere i dati da un'origine dati che può essere database / xml o qualsiasi altro meccanismo di archiviazione.
Model Object or Value Object - Questo oggetto è un semplice POJO contenente metodi get / set per memorizzare i dati recuperati utilizzando la classe DAO.
Implementazione
Creeremo un oggetto Student che funge da Model o Value Object. StudentDao è l'interfaccia oggetto di accesso ai dati. StudentDaoImpl è una classe concreta che implementa l'interfaccia oggetto di accesso ai dati. DaoPatternDemo , la nostra classe demo utilizzerà StudentDao per dimostrare l'uso del pattern Data Access Object.
Passo 1
Crea oggetto valore.
Student.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;
}
}
Passo 2
Crea interfaccia oggetto di accesso ai dati.
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);
}
Passaggio 3
Crea una classe concreata che implementa l'interfaccia sopra.
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");
}
}
Passaggio 4
Usa StudentDao per dimostrare l'utilizzo del pattern Data Access Object.
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()+" ]");
}
}
Passaggio 5
Verifica l'output.
Student: [RollNo : 0, Name : Robert ]
Student: [RollNo : 1, Name : John ]
Student: Roll No 0, updated in the database
Student: [RollNo : 0, Name : Michael ]
Il modello di progettazione del front controller viene utilizzato per fornire un meccanismo di gestione delle richieste centralizzato in modo che tutte le richieste vengano gestite da un unico gestore. Questo gestore può eseguire l'autenticazione / autorizzazione / registrazione o il monitoraggio della richiesta e quindi passare le richieste ai gestori corrispondenti. Di seguito sono riportate le entità di questo tipo di design pattern.
Front Controller - Un unico gestore per tutti i tipi di richieste in arrivo all'applicazione (sia web che desktop).
Dispatcher - Front Controller può utilizzare un oggetto dispatcher che può inviare la richiesta al corrispondente gestore specifico.
View - Le viste sono l'oggetto per il quale vengono effettuate le richieste.
Implementazione
Creeremo un FrontController , Dispatcher che funga da Front Controller e Dispatcher corrispondentemente. HomeView e StudentView rappresentano varie viste per le quali le richieste possono arrivare al front controller.
FrontControllerPatternDemo , la nostra classe demo utilizzerà FrontController per dimostrare il modello di progettazione del controller anteriore.
Passo 1
Crea viste.
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");
}
}
Passo 2
Crea Dispatcher.
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();
}
}
}
Passaggio 3
Crea 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);
}
}
}
Passaggio 4
Utilizzare FrontController per dimostrare il modello di progettazione del controller anteriore.
FrontControllerPatternDemo.java
public class FrontControllerPatternDemo {
public static void main(String[] args) {
FrontController frontController = new FrontController();
frontController.dispatchRequest("HOME");
frontController.dispatchRequest("STUDENT");
}
}
Passaggio 5
Verifica l'output.
Page requested: HOME
User is authenticated successfully.
Displaying Home Page
Page requested: STUDENT
User is authenticated successfully.
Displaying Student Page
Il pattern di progettazione del filtro di intercettazione viene utilizzato quando si desidera eseguire una pre-elaborazione / post-elaborazione con richiesta o risposta dell'applicazione. I filtri vengono definiti e applicati alla richiesta prima di passare la richiesta all'effettiva applicazione di destinazione. I filtri possono eseguire l'autenticazione / autorizzazione / registrazione o il monitoraggio della richiesta e quindi passare le richieste ai gestori corrispondenti. Di seguito sono riportate le entità di questo tipo di design pattern.
Filter - Filtro che eseguirà determinate attività prima o dopo l'esecuzione della richiesta da parte del gestore delle richieste.
Filter Chain - Filter Chain trasporta più filtri e aiuta a eseguirli in un ordine definito sul target.
Target - L'oggetto di destinazione è il gestore delle richieste
Filter Manager - Filter Manager gestisce i filtri e la catena di filtri.
Client - Client è l'oggetto che invia la richiesta all'oggetto Target.
Implementazione
Creeremo un FilterChain , FilterManager , Target , Client come vari oggetti che rappresentano le nostre entità. AuthenticationFilter e DebugFilter rappresentano i filtri concreti.
InterceptingFilterDemo , la nostra classe demo utilizzerà Client per dimostrare l'intercepting Filter Design Pattern.
Passo 1
Crea interfaccia filtro.
Filter.java
public interface Filter {
public void execute(String request);
}
Passo 2
Crea filtri di cemento.
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);
}
}
Passaggio 3
Crea target
Target.java
public class Target {
public void execute(String request){
System.out.println("Executing request: " + request);
}
}
Passaggio 4
Crea catena di filtri
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;
}
}
Passaggio 5
Crea Gestione filtri
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);
}
}
Passaggio 6
Crea cliente
Client.java
public class Client {
FilterManager filterManager;
public void setFilterManager(FilterManager filterManager){
this.filterManager = filterManager;
}
public void sendRequest(String request){
filterManager.filterRequest(request);
}
}
Passaggio 7
Utilizzare il client per dimostrare l'intercettazione del pattern di progettazione del filtro.
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");
}
}
Passaggio 8
Verifica l'output.
Authenticating request: HOME
request log: HOME
Executing request: HOME
Il modello di progettazione del localizzatore di servizi viene utilizzato quando si desidera individuare vari servizi utilizzando la ricerca JNDI. Considerando l'elevato costo di ricerca di JNDI per un servizio, il pattern Service Locator utilizza la tecnica di memorizzazione nella cache. Per la prima volta che è richiesto un servizio, Service Locator cerca in JNDI e memorizza nella cache l'oggetto servizio. Un'ulteriore ricerca o lo stesso servizio tramite Service Locator viene eseguita nella sua cache, il che migliora notevolmente le prestazioni dell'applicazione. Di seguito sono riportate le entità di questo tipo di design pattern.
Service- Servizio effettivo che elaborerà la richiesta. Il riferimento a tale servizio deve essere esaminato nel server JNDI.
Context / Initial Context -JNDI Contesto, porta il riferimento al servizio utilizzato a scopo di ricerca.
Service Locator - Service Locator è un unico punto di contatto per ottenere servizi tramite ricerca JNDI, memorizzando i servizi nella cache.
Cache - Cache per memorizzare i riferimenti dei servizi per riutilizzarli
Client - Client è l'oggetto che richiama i servizi tramite ServiceLocator.
Implementazione
Creeremo un ServiceLocator , InitialContext , Cache , Service come vari oggetti che rappresentano le nostre entità. Service1 e Service2 rappresentano servizi concreti.
ServiceLocatorPatternDemo , la nostra classe demo funge da client qui e utilizzerà ServiceLocator per dimostrare il modello di progettazione di Service Locator.
Passo 1
Crea interfaccia di servizio.
Service.java
public interface Service {
public String getName();
public void execute();
}
Passo 2
Crea servizi concreti.
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";
}
}
Passaggio 3
Crea InitialContext per la ricerca 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;
}
}
Passaggio 4
Crea cache
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);
}
}
}
Passaggio 5
Crea localizzatore di servizi
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;
}
}
Passaggio 6
Utilizzare ServiceLocator per dimostrare il modello di progettazione di Service Locator.
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();
}
}
Passaggio 7
Verifica l'output.
Looking up and creating a new Service1 object
Executing Service1
Looking up and creating a new Service2 object
Executing Service2
Returning cached Service1 object
Executing Service1
Returning cached Service2 object
Executing Service2
Il pattern Transfer Object viene utilizzato quando vogliamo passare dati con più attributi in un colpo solo da client a server. L'oggetto di trasferimento è noto anche come oggetto valore. Transfer Object è una semplice classe POJO con metodi getter / setter ed è serializzabile in modo da poter essere trasferita sulla rete. Non ha alcun comportamento. La business class lato server normalmente recupera i dati dal database e riempie il POJO e lo invia al client o lo trasmette per valore. Per il client, l'oggetto di trasferimento è di sola lettura. Il client può creare il proprio oggetto di trasferimento e passarlo al server per aggiornare i valori nel database in un colpo solo. Di seguito sono riportate le entità di questo tipo di design pattern.
Business Object - Servizio aziendale che riempie l'oggetto di trasferimento con i dati.
Transfer Object -Semplice POJO, con metodi per impostare / ottenere solo attributi.
Client - Il cliente richiede o invia il Transfer Object a Business Object.
Implementazione
Creeremo uno StudentBO come Oggetto Business, Studente come Oggetto Trasferimento che rappresenta le nostre entità.
TransferObjectPatternDemo , la nostra classe demo funge da cliente qui e utilizzerà StudentBO e Student per dimostrare Transfer Object Design Pattern.
Passo 1
Crea oggetto di trasferimento.
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;
}
}
Passo 2
Crea oggetto aziendale.
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");
}
}
Passaggio 3
Usa StudentBO per dimostrare Transfer Object Design Pattern.
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()+" ]");
}
}
Passaggio 4
Verifica l'output.
Student: [RollNo : 0, Name : Robert ]
Student: [RollNo : 1, Name : John ]
Student: Roll No 0, updated in the database
Student: [RollNo : 0, Name : Michael ]