1 Goal

Transcription

1 Goal
1 Goal
The goal of this work is to present an overview of Creational design patterns and to present a
modelling tool Together Control Center in terms of creating and applying design patterns that
are provided by this tool. Therefore, an example of the Abstract Factory pattern has to be
created and the designing process has to be evaluated.
2
Creational Patterns
Creational design patterns are all about class instantiation. In particular, creational patterns
deal with system independence from object composition, creation and representation.
Creational design patterns can be further divided into class-creational patterns and objectcreational patterns. Class Creational Pattern uses inheritance to vary the class that’s
instantiated. Factory Method is an example of class-creational Pattern. Object-creational
pattern will delegate instantiation to another object. The remaining four creational patterns
belong to this category(we discuss creational patterns presented in [GoF]).
Creational patterns have two particular properties:
•
they encapsulate knowledge about the classes that the system uses
•
they hide how objects are created and put together.
All the creational patterns are very close related. Sometimes, creational patterns are
competitors: there are cases when either Prototype or Abstract Factory could be used
profitably. At other times they are complementary: Abstract Factory might store a set of
Prototypes from which to clone and return product objects [GOF], Builder can use one of the
other patterns to implement which components get built. Abstract Factory, Builder, and
Prototype can use Singleton in their implementation. [GOF]
2.1 Factory Method
Factory method pattern can be often found in OO programs. A Factory method pattern returns
an instance of one of several possible classes. Which class it will return depends on provided
arguments. Usually all the classes it returns implement one interface but each of them is
optimised for specific kind of data.
Structure
Product
Creator
FactoryMethod()
AnOperation()
ConcreteProduct
ConcreteCreator
FactoryMethod()
…
product =FactoryMethod()
….
return new ConcreteProduct
In the structure presented above, the following participants are shown: Product,
ConcreteProduct, Creator and ConcreteCreator. Product defines an interface of objects the
Factory method creates where the ConcreteProduct implements that interface. Creator
declares the factory method, which returns an object of type Product. ConcreteCreator
overrides the foctory method to return an instance of a ConcreteProduct.
The cases when the factory method pattern should be considered are the following:
•
A class can’t anticipate which kind of class of objects it must create.
•
A class uses its subclasses to specify which objects it creates.
•
You want to localize the knowledge of which class gets created.
2.2 Abstract Factory
The abstract factory pattern is the next level of abstraction of a Factory method pattern. This
pattern should be considered when you want to return one of several related classes of objects,
each of which can return several different objects on request. Thus, the Abstract Factory is a
factory object that returns one of several concrete factories.
One example of this pattern is given in Ch.3.1.
Structure
AbstractFactory
Client
CreateProductA()
CreateProductB ()
AbstractProductA
ProductA2
ConcreteFactory1
ConcreteFactory2
CreateProductA()
CreateProductB ()
CreateProductA()
CreateProductB()
ProductA1
AbstractProductB
ProductB2
ProductB1
The participants in the structure are: AbstractFactroy, ConcreteFactory, AbstractProduct,
ConcreteProduct and the Client. AbstractFactory declares an interface for operations that
create abstract product objects. AbstractProduct declares an interface for one type of product
object. ConcreteProduct implements the AbstractProduct interface as well as defines a
product object to be created by corresponding ConcreteFactory.
One important issue about abstract factory is that it isolates the concrete classes that are
generated. The class names of this classes are hidden in the factory, so the client doesn’t have
a direct access to them.
It is easy to switch between these concrete product classes. Since the only one kind of
concrete class is generated, it is guaranteed that classes from the different product families
won’t be used.
One drawback of abstract factory is that supporting a new kind of product is difficult due to
fact that AbstractFactory fixes the set of products that can be created.
2.3 Builder
The intent of the Builder pattern is to separate the construction of a complex object from its
representation so that the same construction process can create different representations.
Consequently this pattern should be applied when the algorithm for creating a complex object
should be independent of the parts that make up the object and how they are assembled
together. Another case could be when the construction process must allow different
representations for the object that is created.
Structure
Director
Builder
Construct()
BuildPart()
for all objects in structure
builder ->BuildPart()
}
ConcreteBuilder
Product
BuildPartA
()
GetResultB
()
The Builder specifies an abstract interface for creating parts of a Product object.
ConcreteBuilder constructs and assembles parts of the product by implementing the Builder
interface and provides an interface for retrieving the product. Director constructs an object
using the Builder interface and the Product is the complex object that is constructed.
A Builder lets you vary the internal representation of the product it builds. Also, it hides how
the product is assembled.
2.4 Singleton
The singleton pattern could be mentioned as an exception of creational patterns while it is not
exactly the case of object creation. The class can ensure that no more then one instance can be
created, and it provides a global point of access to this instance.
Structure
Singleton
Static Instance()
SingletonOperation ()
GetSingletonData ()
Static uniqueInstance
singletonData
return uniqueInstance
Singleton defines an instance operation that lets clients access its unique instance.
The consequences of using the singleton pattern can be the following:
•
It can be difficult to subclass a Singleton, since this can only be done if the base Singleton
class has not yet been instantiated.
•
It is easy to change a Singleton to allow more than one instance.
2.5 Prototype:
The Prototype pattern specifies the kinds of objects to create using a prototypical instance and
creates new objects by copying the prototype. The structure of this pattern is shown below.
Structure
Client
Prototype
Operation()
Clone()
p = prototype->Clone()
ConcretePrototype1
Clone()
return of self
ConcretePrototype2
Clone()
return copy of self
As shown above, this pattern has three participants, Prototype, ConcretePrototype, and Client.
The prototype declares the interface for cloning itself, while the ConcretePrototype
implements this interface. The Client creates a new object by asking the prototype to clone
itself. This is the only collaboration present. That is, clients ask prototypes to clone
themselves.
Prototype hides concrete product classes from clients and allows clients to work with
unmodified application-specific classes. In addition, the Prototype pattern:
•
Allows for addition and deletion of products at run-time.
•
Can specify new objects by varying values.
•
Can specify new objects by varying structure.
•
Reduces the amount of subclasses required.
•
Allows for the configuration of an application with dynamic classes.
•
Requires each subclass to implement the clone method, which could be non-trivial.
There are three noted implementation issues for the prototype pattern:
•
A prototype manager may be required when the number of prototypes is dynamic.
•
The implementation of the Clone() method can be problematic.
3 TogetherSoft
Here, I’d like to present an example of a software-modelling tool that, among the other things,
provides a possibility to apply design patterns for creating classes or links and for refactoring
existing model applying specified design pattern.
Automatisation of the modelling process is very important, especially nowadays, when the
demand for complex software systems is growing enormously.
ToghtherSoft was founded by Peter Coad, who helped developed the Coad-Yourdon objectoriented analysis and design methodology. TogetherSoft calls ControlCenter a Model-BuildDeploy Platform. These are the possibilities that it provides: “With it, you can: model - EJB pattern - edit - compile - debug - version - doc - metric/audit - provision - assemble - deploy run." It has a UML tool, a programming editor, round-trip code engineering, software matrix
tools, etc. It is a powerful CASE tool, although, several drawbacks were encountered while
designing a model with an Abstract Factory design pattern. Description of these drawbacks is
given at the end of this chapter. Below, in Fig.1, the graphical user interface of the
Together5.5 is presented.
Figure 1. A screenshot of the Together 5.5
One of the advantages of design patterns is that they provide a vocabulary and starting point
for design, and many of them can be seen as general-purpose classes in object-oriented class
libraries. Patterns are used to create frequently used elements, modify them, or to implement
useful source code constructions or solutions to previously defined model. Among the
patterns provided with Together there are the Coad Components, several GoF patterns
including Abstract Facrory, Visitor, Observer; Singleton, a set of EJB classes for various
specifications, etc.
3.1 Example
With the purpose of better understanding the structure of the Abstract Factory pattern, a
simple example was elaborated. Furthermore, Together5.5 was chosen as a modelling tool for
the process of implementation. Thus, this will help us to investigate several features provided
by Together5.5 as well as to get acquainted with the Abstract Factory design pattern.
The example describes an implementation of a system for a “car service center”. There are
two type of products that service center support: BMW spare parts (such as BMWEngine,
BMWChassis, and BMWBody) and respectively Opel spare parts (OpelEngine, OpelChassis,
and OpelBody). These two product types extend Sparefactory - abstract product class. To
create either of these family of products there are two concrete factory classes,
BMWSparefactory and OpelSparefactory extending from Sparefactory (Abstract Factory)
class. Thus, to order (create) specific type of product, the client accesses Sparefactory
(Abstract Factory) and Abstract Product(s) (Engine, Body, Chassis) to create concrete
product(s) such as (BMWEngine, BMWChassis, and BMWBody).
Sample Code
//Sparefactory(Abstract Factory)
public interface Sparefactory {
Body createBody();
Engine createEngine();
Chassis createChassis();
}
//BMWSparefactory(Concrete Factory1)
public class BMWSparefactory implements Sparefactory {
public Body createBody(){
return new BMWBody();
}
public Engine createEngine(){
return new BMWEngine();
}
public Chassis createChassis(){
return new BMWChassis();
}
}
//OpelSparefactory (Concrete Factory2)
public class OpelSparefactory implements Sparefactory {
public Body createBody(){
return new OpelBody();
}
public Engine createEngine(){
return new OpelEngine();
}
public Chassis createChassis(){
return new OpelChassis();
}
}
//Engine (Abstract product1)
public interface Engine {
void engineOperation();
}
//Chassis (Abstract product2)
public interface Chassis {
void shssisOperation1();
void chassisOperation2();
}
//Body (Abstract product3)
public interface Body {
void bodyOperation1();
void bodyOperation2();
}
//BMWBody (Product BMWBody)
public class BMWBody implements Body {
public void bodyOperation1(){
//Write your code here
}
public void bodyOperation2(){
//Write your code here
}
}
//BMWEngine (Product BMWEngine)
public class BMWEngine implements Engine {
public void engineOperation(){
//Write your code here
}
}
//BMWChassis (Product BMWChassis)
public class BMWChassis implements Chassis {
public void shssisOperation1(){
//Write your code here
}
public void chassisOperation2(){
//Write your code here
}
}
//OpelBody (Product OpelBody)
public class OpelBody implements Body {
public void bodyOperation1(){
//Write your code here
}
public void bodyOperation2(){
//Write your code here
}
}
//OpelEngine (Product OpelEngine)
public class OpelEngine implements Engine {
public void engineOperation(){
//Write your code here
}
}
//OpelChassis (Product OpelChassis)
public class OpelChassis implements Chassis {
public void shssisOperation1(){
//Write your code here
}
public void chassisOperation2(){
//Write your code here
}
}
Then we create a client (Car service center) class that can create
(deliver) product(s) (Body, Engine, Chassis) of the same family (BMW).
//Client
public class Client {
public static void main(String[] args)
Sparefactory BMWsf=new BMWSparefactory();
Engine
BMWEng=BMWsf.createEngine();
Body
BMWBody=BMWsf.createBody();
Chassis
BMWSh=BMWsf.createChassis();
}
}
The class diagram was created using the diagram editor and design pattern window.
Together5.5 can automatically adjust the layout of the diagram. The presentation of
automatically adjusted layout of the class diagram is given in Fig.2, so you can personally
evaluate its design comprehensiveness.
3.2 Complexity simplification with related patterns
One important issue in the design model presented above is extensibility. If we would like to
add another family of products (Mercedes, Ford, etc..) we had to create another concrete
factory class. Several product types can be painful and to avoid parallel hierarchy of concrete
factories with respect to the products, we can have one concrete factory instead. This concrete
factory uses a “prototype-based” approach where the concrete factory is initialised with a
prototypical instance of each product in the family and it creates a new product by cloning its
prototype (more about Prototype see in Ch.2.5).
The concrete factory can be implemented as a singleton in case if we want to be sure in
uniqueness of the concrete factory which creates all the related objects of one product family
(more about Singleton see in Ch.2.4).
When new products are added to the family, one new factory method has to be added to the
concrete factory. This can be performed by having one factory method taking the kind of
product object, as argument along with parameters to initialise (more about Factory method
see in Ch.2.1).
3.3 Drawbacks and their comparison with features
Together5.5 generated the source code presented above (except the Client class) from the
diagram editing tab, that was found really helpful in the process of model designing using, as
TogetherSoft call it, “Pattern-builder expert”. But this is not exactly true because Together5.5
exhibit several drawbacks in applying/creating the Abstract Factory design pattern. For
clearer distinction of these drawbacks I first present a number of core features that the
developers of the Together5.5 affirm to provide.
•
•
Simultaneous round-trip engineering
•
Edit your code and your diagram auto-updates
•
Edit your diagram and your source code auto-updates
Pattern-builder-expert
•
Allows to select and configure a pattern from a “Design pattern window”
•
Synchronises both diagram and code
interface
Sparefactory
interface
Body
Factory
Product
+Body createBody
+Engine createEngine
+Chassis createChassis
Factory
Factory
Factory
Factory
Product
interface
Chassis
+void chassisOperation1
+void chassisOperation2
Concrete factory
OpelSparefactory
+Body createBody
+Engine createEngine
+Chassis createChassis
Concrete product Product Concrete productProduct
OpelChassis
BMWChassis
BMWSparefactory
+void bodyOperation1
+void bodyOperation2
Product
interface
EngineProduct
Concrete product Concrete product
BMWBody
OpelBody
+Body createBody
+void bodyOperation1+void bodyOperatio
+Engine createEngine +void engineOperation
+void bodyOperation2+void bodyOperatio
+Chassis createShassis
Product
Concrete product
Product
ConcreteProduct
product
BMWEngine
OpelEngine
+void shassisOperation1+void chassisOperation1
+void engineOperation+void engineOperation
+void shassisOperation2+void chassisOperation2
Figure 2. “car service center” class diagram.
The designing process started with Design pattern window. Using this window the user
should be able to: first, specify the pattern that she wishes to use, and second, to set all the
participants from the selected pattern. Also, in this window there is a text area where the
description of the selected pattern is given. The pattern description was found very helpful.
Everything went well until:
1. more than one ConcreteFactory had to be specified. The problem is that the user can not
specify (create) more than one ConcreteFactory in the process of the Abstract Factory
pattern creation. That means that the user has to enter the Design pattern window and
specify the ConcreteFactory participant as many times as the number of concrete factories
is. This is in contradiction with the User’s Guide and tool’s functionality description of
the tool. There is said that if the there are more than one kind of participants in the pattern
then they can be specified (where it is possible by definition of the pattern) sequentially
in the same field (separated by comma).
2. the name for ConcreteProduct had to be specified. It was unusual to notice that there is no
possibility to change the name of ConcreteProduct in the Design pattern window.
Suggested value for concrete product participants were: Concreteproduct1,
Concreteproduct2, etc.. That means that the user can not specify her values for the
pattern’s participant names. Again, this opposes to what the developers provide in the
description of Together’s features.
3. at last, when everything was created I wanted to change the name of a package where all
the classes were grouped. So, using the diagram pane the name of the package was
changed. Nevertheless, no changes (name of the package) have been made in each class
from this package. Again we can see that there are contradictions with what is specified in
core features (simultaneous round-trip engineering).
In addition to what was described earlier I would like to say that all these drawbacks were not
found when implementing other creational patterns that Together5.5 provides. This leads to
conclusion that there are some imperfections in the implementation of Abstract Factory
pattern in Together5.5, which must be eliminated.
4 Conclusion
The overview of creational design patterns was given in the first part of this paper.
Modelling tool Together5.5 was analysed in terms of creating and applying Abstract Factory
pattern. In general the tool provides a lot of functional possibilities and has a good user
interface. Nevertheless, it was found that there are several imperfections referred to process of
creation and editing the Abstract Factory design pattern using this modelling tool. These
imperfections