Read also: JSF and Factory pattern (CDI aspects) - part II
The Factory pattern is commonly used to create objects via:
The Factory pattern is commonly used to create objects via:
·
factory
method pattern - defines a method that creates and return new objects
·
abstract
factory pattern - delegates a subclass to create new objects
The main
idea consist in the fact that the object is abstracted away from where it will
be used!
Factory method pattern
Factory Method is a Creational Design Pattern with the following object structural:
The GoF (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) book describes this pattern as "An interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses."
Let's suppose that we have the following objects (artifacts):
Factory Method is a Creational Design Pattern with the following object structural:
The GoF (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) book describes this pattern as "An interface for creating an object, but let the subclasses decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses."
Let's suppose that we have the following objects (artifacts):
public
interface Artifact {}
public class
Artifact_A implements Artifact {
public Artifact_A() {}
}
public class
Artifact_B implements Artifact {
public Artifact_B() {}
}
Further,
we define an abstract class that will be extended later by the concrete
implementations. Here we write the factory method signature - this method
should be capable to return Artifacts:
public
abstract class ArtifactFactory {
public abstract Artifact getArtifact();
}
Next, we
have two factory implementations:
public class
ArtifactFactory_A extends ArtifactFactory {
@Override
public Artifact getArtifact() {
return new Artifact_A();
}
}
public class
ArtifactFactory_B extends ArtifactFactory {
@Override
public Artifact getArtifact() {
return new Artifact_B();
}
}
Now, some simple usages:
ArtifactFactory
artifactFactory = new ArtifactFactory_A();
Artifact
artifact = artifactFactory.getArtifact();
Artifact_A
artifact_A = (Artifact_A)artifactFactory.getArtifact();
Abstract factory pattern
Abstract Method is a Creational Design Pattern with the following object structural:
The GoF (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) book describes this pattern as "Provides an interface for creating families of related or dependent objects without specifying their concrete classes."
Abstract Method is a Creational Design Pattern with the following object structural:
The
abstract factory pattern relies on factories that encapsulate groups of
factories and control over how the client accesses them. Is beyond our aim to
discuss this pattern.
JSF factory pattern implementation
JSF uses the
factory
method pattern for exposing a set of artifacts. We can point out some
of them as: PartialViewContext, RenderKit, ExceptionHandler, VisitContext, ExternalContext, Flash, etc. These
are abstract classes that belongs to JSF specification and have proper
implementations in Mojarra/MyFaces of type ArtifactImpl. For each
such artifact, JSF provides a factory class capable to create and return a new ArtifactImpl instance.
JSF
specification provides the abstract factory classes that will be extended by the
concrete implementations. The names of these classes follows the pattern ArtifactFactory, and the implementations
(Mojarra and Apache MyFaces) follows the pattern ArtifactFactoryImpl.
For
example, the ExceptionHandler artifact has the following abstract factory attached
in the specification:
// JSF 2.0 specification
public abstract
class ExceptionHandlerFactory implements
FacesWrapper<ExceptionHandlerFactory> {
public ExceptionHandlerFactory() {
}
public ExceptionHandlerFactory getWrapped() {
return null;
}
public abstract ExceptionHandler
getExceptionHandler();
}
Now, the concrete implementations extends ExceptionHandlerFactory. For
example, the Mojarra implementation is com.sun.faces.context.ExceptionHandlerFactoryImpl:
public class
ExceptionHandlerFactoryImpl extends ExceptionHandlerFactory {
public ExceptionHandlerFactoryImpl() {
}
public ExceptionHandler getExceptionHandler()
{
// return an ExceptionHandler implementation instance
}
...
}
In Apache
MyFaces we have the implementation available in
org.apache.myfaces.context.ExceptionHandlerFactoryImpl:
public class
ExceptionHandlerFactoryImpl extends ExceptionHandlerFactory {
@Override
public ExceptionHandler getExceptionHandler()
{
// return an ExceptionHandler implementation instance
}
}
}
In JSF,
the factories are initialized by FactoryFinder, which
recognizes if a custom factory has a delegating constructor—a one argument constructor
for the type of the factory. JSF is very flexible, so we can write custom
factories implementations to return custom artifacts and/or to alter an
existing factory instance (see the factory getWrapper() method
above).
This is
useful when we want to wrap standard factory from JSF, because FactoryFinder will pass
in the previously known factory, usually the built-in one. Factory instances
are obtained as follows:
XXXFactory factory = (XXXFactory) FactoryFinder.getFactory(FactoryFinder.XXX_FACTORY);
For
example, RenderKitFactory can be
found using the following code:
RenderKitFactory
factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
Commonly,
when we need to instruct JSF to return a custom artifact provided via a factory, we follow three main
steps:
1. Write the custom artifact (JSF
provides wrappers for almost all artifacts, so, most probably you will extend
the corresponding wrapper - of course, if you don't need the original artifact
instance or you need to implement the entire set of artifact abstract methods, then
you don't need the wrapper class).
2. Write the factory implementation by
extending the ArtifactFactory class and
overriding the desired methods (obviously, among others, we need here the method capable to return the artifact instances).
3.Instruct JSF to use our factory
implementation by making the required configurations in faces-config.xml via the <factory> tag.
You can
see an example of writing a custom RenderKitFactory in Write
Custom RenderKitFactory Skeleton. More examples are available in chapter
5 of book, Mastering
JavaServer Faces 2.2.
Niciun comentariu :
Trimiteți un comentariu