My JSF Books/Videos My JSF Tutorials OmniFaces/JSF PPTs
JSF 2.3 Tutorial
JSF Caching Tutorial
JSF Navigation Tutorial
JSF Scopes Tutorial
JSF Page Author Beginner's Guide
OmniFaces 2.3 Tutorial Examples
OmniFaces 2.2 Tutorial Examples
JSF Events Tutorial
OmniFaces Callbacks Usages
JSF State Tutorial
JSF and Design Patterns
JSF 2.3 New Features (2.3-m04)
Introduction to OmniFaces
25+ Reasons to use OmniFaces in JSF
OmniFaces Validators
OmniFaces Converters
JSF Design Patterns
Mastering OmniFaces
Reusable and less-verbose JSF code

My JSF Resources ...

Java EE Guardian
Member of JCG Program
Member MVB DZone
Blog curated on ZEEF
OmniFaces is an utility library for JSF, including PrimeFaces, RichFaces, ICEfaces ...

.

.

.

.

.

.

.

.


[OmniFaces Utilities] - Find the right JSF OmniFaces 2 utilities methods/functions

Search on blog

Petition by Java EE Guardians

Twitter

duminică, 27 septembrie 2015

JSF and Strategy design pattern - part I (plain code)

Strategy is a Behavioral Design Pattern with the following object structural:
The GoF (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) book describes this pattern as a pattern that "Defines a set of encapsulated algorithms that can be swapped to carry out a specific behaviour."
The above diagram (object strucutural) can be explained in a few words: in the strategy pattern, multiple algorithms are represented as concrete strategy classes, and they share a common strategy interface. A context object contains a reference to a strategy. In order to obtain different behaviors we change the context's, strategy. These behaviors are different, but they affect data from the context.

So, the strategy pattern (also known as policy pattern) is especially used when multiple versions/variations of an algorithm are required. Basically, we own multiple algorithms for a specific task (e.g. sorting an array) and we allows the client to choose the desired implementation to be used at runtime (e.g. in Java, we can provide multiple implementations of Comparator, and we pass the desired implementation as parameter to the Arrays#sort(T[] a, Comparator<? super T> c) method).

Notice that the strategy pattern is very much like the state pattern. In the state pattern, the context contains state as instance variable and we have multiple tasks (jobs) whose implementation can be dependent on the state. By the other hand, in the strategy pattern,  the strategy represents the argument of a method and context object doesn’t have any variable to store it.

For our example, we will try to implement a simple application for archiving files. We start with the strategy interface, which in our case contains the declaration of a method used for archiving files, ArchiverStrategy:

public interface ArchiverStrategy {

 public void archive(String path, List<String> files);
}

Further, we provide some implementation of this interface. Practically, we implement the algorithms for creating archives. Let's suppose that we have two such algorithms, one for fast archiving (FastArchiverStrategy),and one for slow archiving (SlowArchiverStrategy):

public class FastArchiverStrategy implements ArchiverStrategy {

 private final int compression;

 public FastArchiverStrategy(int compression) {
  this.compression = compression;
 }

 @Override
 public void archive(String path, List<String> files) {
  System.out.println("Fast archiver for " + files + " at compression level " + compression);
 }
}

public class SlowArchiverStrategy implements ArchiverStrategy {

 private final int compression;
 private final int numFastBytes;
 private final int numPasses;

 public SlowArchiverStrategy(int compression, int numFastBytes, int numPasses) {
  this.compression = compression;
  this.numFastBytes = numFastBytes;
  this.numPasses = numPasses;
 }

 @Override
 public void archive(String path, List<String> files) {
  System.out.println("Slow archiver for " + files + " at compression level " + 
     compression + " (Fast Bytes: " + numFastBytes + ", Passes: " + numPasses + ")");
 }
}

Since the algorithms are ready, we can go further and implement the archiver (context), which will require the algorithm used for archiving task in the archive() method, as below:

public class Archiver {
   
 private final List<String> files;  

 public Archiver() {
  this.files = new ArrayList<>();
 }   
   
 public void addFile(String file){
  this.files.add(file);
 }
   
 public void removeFile(String file){
  this.files.remove(file);
 }
   
 public void archive(String path, ArchiverStrategy archiverStrategy){
  archiverStrategy.archive(path, files);
 }   
}

Now, we can perform a simple test:

Archiver archiver = new Archiver();
archiver.addFile("foo.txt");
archiver.addFile("buzz.txt");
       
archiver.archive("SOME_PATH_1", new FastArchiverStrategy(0));
archiver.archive("SOME_PATH_2", new SlowArchiverStrategy(9, 128, 10));

The output will be:

Fast archiver for [foo.txt, buzz.txt] at compression level 0
Slow archiver for [foo.txt, buzz.txt] at compression level 9 (Fast Bytes: 128, Passes: 10)

In the nextpart of this post we will re-write this example in JSF+CDI style.

Niciun comentariu :

Trimiteți un comentariu

JSF BOOKS COLLECTION

Postări populare

OmniFaces/JSF Fans

Visitors Starting 4 September 2015

Locations of Site Visitors