Uploaded by Gray Scale

School of Electrical Engineering and Computing

advertisement
School of Electrical Engineering and Computing
Computer Science and Engineering Department
Software Design and Architecture(CSE3205)
Group Assignment
Object-Oriented Design Patterns
Name
1
2
3
4
ID
Alazar Zerihun
Eyob H/Mikael
Eyob Gebeyehu
Olyad Kassahun
UGR/20281/12
UGR/17083/11
UGR/19939/12
UGR/19751/12
Submission Date:
Submitted To:
Object Oriented Design Patterns
Design Patterns are divided into three categories – creational, structural, and behavioral design patterns.
Most modern languages have adopted techniques and syntax for built-in support for many of these design
patterns, while others remain largely unnecessary.
Creational Patterns
Creational patterns emphasize the automatic creation of objects within code, rather than requiring you to
instantiate objects directly. In most cases, this means that a function or method can call the code
necessary to instantiate new objects on your behalf, so you only need to explicitly modify that object
creation when it is necessary, and allow default behaviors to take over otherwise.
Prototype Pattern
Description
The Prototype pattern is a creational design pattern that allows objects to be created by cloning
existing objects. This pattern provides a convenient way to create new objects by copying all or part
of an existing object and making modifications to it if necessary. The goal of this pattern is to avoid
creating new objects from scratch and instead reuse existing objects that have the desired
characteristics. This can lead to improved performance, as creating a new object from scratch can be
time-consuming and resource-intensive.
Applicability
The Prototype pattern is useful in the following scenarios:




When the classes to instantiate are specified at runtime, and it is not possible to anticipate
the types of objects that will be required.
When you want to reduce the number of classes that are needed in your system.
When an object can be defined by a small number of characteristics that can be copied and
modified.
When you want to create a large number of similar objects, but it is impractical or
impossible to create each object from scratch.
Structure
The Prototype pattern consists of the following components:
Prototype: This is an interface that defines the cloning method that will be used to create new
objects.
Concrete Prototypes: This is a concrete implementation of the Prototype interface. Each concrete
prototype class provides its own implementation of the cloning method to create new objects.
Client: The Client creates a new object by asking a Prototype to clone itself.
Implementation
The following steps are involved in implementing the Prototype pattern:
1. Declare a Prototype interface that defines the cloning method.
2. Create concrete prototype classes that implement the cloning method. These classes should
provide their own implementation of the cloning method to create new objects.
3. Store a reference to one of the concrete prototype objects in a prototype registry.
4. The Client creates a new object by asking the prototype registry for a reference to a
concrete prototype object and then calling its cloning method.
5. The concrete prototype object's cloning method creates a new object by copying all or part
of the existing object and making modifications to it if necessary.
Sample case study
Suppose we are doing a sales analysis on a set of data from a database. Normally, we would copy the
information from the database, encapsulate it into an object and do the analysis. But if another
analysis is needed on the same set of data, reading the database again and creating a new object is
not the best idea. If we are using the Prototype pattern then the object used in the first analysis will
be cloned and used for the other analysis.
The Client is here one of the methods that process an object that encapsulates information from the
database. The ConcretePrototype classes will be classes that, from the object created after
extracting data from the database, will copy it into objects used for analysis.
Builder Pattern
Description
The Builder pattern is a creational design pattern that allows you to construct complex objects step
by step. The key idea behind this pattern is to separate the construction of an object from its
representation. This means that the process of creating an object can be separated into several
steps, each of which is executed by a different object. This pattern is used to create complex objects
with many components that can be constructed in different ways. By separating the construction
process from the representation, you can hide the implementation details of creating an object and
focus on the objects themselves.
Applicability
The Builder pattern is useful in the following scenarios:





When you need to create an object that has many components that can be constructed in
different ways.
When you want to separate the construction of an object from its representation.
When you want to hide the implementation details of creating an object and focus on the
objects themselves.
When you want to make it easier to change the construction process without affecting the
representation.
When you want to create a family of related objects that can be constructed in different
ways.
Structure
The Builder pattern consists of the following components:
•
•
•
•
Builder: This is an interface that defines the methods that will be used to construct an
object.
Concrete Builder: This is a concrete implementation of the Builder interface. Each concrete
builder class provides its own implementation of the methods that are used to construct an
object.
Director: This is an object that knows how to construct an object using the methods of a
Builder. The Director knows the order in which to call the methods of the Builder to create
an object.
Product: This is the object that is being constructed by the Builder.
Implementation
The following steps are involved in implementing the Builder pattern:
1. Declare a Builder interface that defines the methods that will be used to construct an object.
2. Create concrete builder classes that implement the Builder interface. These classes should
provide their own implementation of the methods that are used to construct an object.
3. Create a Director object that knows how to construct an object using the methods of a
Builder. The Director knows the order in which to call the methods of the Builder to create
an object.
4. The Client creates a Director object and sets a Builder object.
5. The Client asks the Director to construct an object by calling its build method.
6. The Director calls the methods of the Builder to construct the object.
Sample case study
- Students Exams.
If we have an application that can be used by the students of a University to provide them with the
list of their grades for their exams, this application needs to run in different ways depending on the
user that is using it, user that has to log in. This means that, for example, the admin needs to have
some buttons enabled, buttons that needs to be disabled for the student, the common user. The
Builder provides the interface for building form depending on the login information. The
ConcreteBuilders are the specific forms for each type of user. The Product is the final form that the
application will use in the given case and the Director is the application that, based on the login
information, needs a specific form
Structural patterns
Structural patterns focus on the composition of classes and objects. By using inheritance and interfaces,
these patterns allow objects to be composed in a manner that provides new functionality. In most cases, an
interface in object-oriented programming is an abstract type or class which has no logical code but instead
is used to define method signatures and behaviors for other classes that will implement the interface.
Adapter Pattern:
Description: The Adapter pattern is a design pattern that allows objects with incompatible interfaces
to collaborate. It converts the interface of a class into another interface that the client expects. This
allows classes that could not otherwise work together to function. The basic structure of the Adapter
pattern includes a Target interface, an Adapter class, and an Adaptee class. The Target interface
defines the interface that the client expects, the Adapter class adapts the Adaptee class to the
Target interface, and the Adaptee class provides the service that the client needs.
Applicability
The Adapter pattern is useful when:


A class cannot be used because it has an incompatible interface
A client makes use of several independent or incompatible interfaces
Structure
To implement the Adapter pattern, you can use the following techniques:
Object Adapter pattern: In this pattern, you use inheritance to adapt the interface of the Adoptee to
the Target interface. The Adapter class inherits from the Adoptee class and implements the Target
interface.
Class Adapter pattern: In this pattern, you use multiple inheritance to adapt the interface of the
Adoptee to the Target interface. The Adapter class implements both the Target interface and the
Adoptee interface.
The classes/objects participating in adapter pattern:




Target - defines the domain-specific interface that Client uses.
Adapter - adapts the interface Adoptee to the Target interface.
Adoptee - defines an existing interface that needs adapting.
Client - collaborates with objects conforming to the Target interface.
The figure below shows a UML class diagram for the Adapter Pattern:
Sample case study
A classic example of the Adapter pattern is a power adapter for electronic devices. The power
adapter adapts the output of the wall outlet to match the input required by the device. In this
example, the wall outlet is the Adoptee, the power adapter is the Adapter, and the device is the
Target.
Proxy Pattern:
Description
The Proxy pattern is a structural design pattern that provides a placeholder or surrogate object for
another object to control access to it. The main purpose of the Proxy pattern is to act as a
intermediary between a client and the actual object that the client wants to access, thereby allowing
the client to interact with the object indirectly. The basic structure of the Proxy pattern includes a
Subject interface, a Proxy class, and a RealSubject class. The Subject interface defines the interface
that the client expects, the Proxy class controls access to the RealSubject, and the RealSubject
provides the service that the client needs.
One of the key benefits of using the Proxy pattern is that it provides a level of abstraction between
the client and the actual object. This abstraction can be used to control access to the actual object in
various ways, such as by validating client requests, checking if the client has permission to access the
object, or by logging client interactions with the object. This can be useful in a number of situations,
such as when you want to provide a cache of frequently used objects, or when you want to limit the
number of instances of an object that can be created
Applicability
•
•
•
•
•
The Proxy design pattern is applicable when there is a need to control access to an Object, as
well as when there is a need for a sophisticated reference to an Object. Common Situations
where the proxy pattern is applicable are:
Virtual Proxies: delaying the creation and initialization of expensive objects until needed,
where the objects are created on demand (For example creating the RealSubject object only
when the doSomething method is invoked).
Remote Proxies: providing a local representation for an object that is in a different address
space. A common example is Java RMI stub objects. The stub object acts as a proxy where
invoking methods on the stub would cause the stub to communicate and invoke methods on
a remote object (called skeleton) found on a different machine.
Protection Proxies: where a proxy controls access to RealSubject methods, by giving access
to some objects while denying access to others.
Smart References: providing a sophisticated access to certain objects such as tracking the
number of references to an object and denying access if a certain number is reached, as well
as loading an object from database into memory on demand.
Structure
The participants classes in the proxy pattern are:



Subject - Interface implemented by the RealSubject and representing its services. The
interface must be implemented by the proxy as well so that the proxy can be used in any
location where the RealSubject can be used.
Proxy
 Maintains a reference that allows the Proxy to access the RealSubject.
 Implements the same interface implemented by the RealSubject so that the Proxy
can be substituted for the RealSubject.
 Controls access to the RealSubject and may be responsible for its creation and
deletion.
 Other responsibilities depend on the kind of proxy.
RealSubject - the real object that the proxy represents.
The figure below shows a UML class diagram for the Proxy Pattern:
Implementation
To implement the Proxy pattern, you need to do the following:
1. Define the Subject interface, which will declare the methods that the client is expected to
use to interact with the object.
2. Create the RealSubject class, which will implement the methods declared by the Subject
interface and provide the actual service that the client needs.
3. Create the Proxy class, which will implement the Subject interface and control access to the
RealSubject. The Proxy class can also perform additional tasks such as validating client
requests, checking if the client has permission to access the object, or logging client
interactions with the object.
4. The client uses the Subject interface to interact with the object indirectly through the Proxy
class.
Sample case study
Consider a scenario where you are building a system to manage access to sensitive information, and
you want to ensure that only authorized users are able to access the information. You can use the
Proxy pattern to implement this system by creating a Protection Proxy to control access to the
information. The Subject interface can define the methods for accessing the information, the
RealSubject can contain the actual sensitive information, and the Proxy can validate client requests
and determine if the client has the necessary permissions to access the information.
For example, you could create a Subject interface called Information, and have it declare a method
called getData(). The RealSubject class, called SensitiveInformation, would implement the
Information interface and provide the actual sensitive data. The Proxy class, called
AccessControlProxy, would implement the Information interface, control access to the
SensitiveInformation, and only allow access if the client has the necessary permissions. The client
would use the Information interface to interact with the object indirectly through the
AccessControlProxy.
This would ensure that the sensitive information is protected, as the client would only be able to
access it through the AccessControlProxy, and only if the client has the necessary permissions.
Behavioral Patterns
a complex arrangement of two or more responses that occur in a prescribed order. Behavior
patterns are also referred to as chains of behavior, highlighting their nature as a complex linking of
simpler segments of behavior.
Mediator pattern
Description
The Mediator design pattern is a behavioral pattern that provides a centralized way to handle
communication between objects, thereby reducing the complexity and coupling between objects.
The Mediator pattern defines an object that acts as an intermediary between other objects and
handles all communication between them.
The Mediator pattern is used to encapsulate the communication between objects and promote
loose coupling between them. The objects communicate with the Mediator, rather than directly
with each other, which reduces the coupling between objects and makes it easier to maintain the
system.
The Mediator pattern is used when you have a complex system with many objects that interact with
each other and you want to avoid tight coupling between them. The Mediator ensures that the
objects interact with each other only through the Mediator and reduces the coupling between
objects, making it easier to maintain the system.
Applicability
The Mediator pattern should be used when:
1. There are complex interactions between objects and you want to simplify the interactions by
centralizing the communication.
2. You want to reduce the coupling between objects and make it easier to maintain the system.
3. You want to provide a centralized point for communication between objects.
Structure
The Mediator pattern typically includes the following components:
1. Mediator interface: Defines the methods that the objects will use to communicate with the
Mediator.
2. Concrete Mediator: Implements the Mediator interface and handles the communication
between the objects.
3. Colleague interface: Defines the methods that the objects will use to communicate with the
Mediator.
4. Concrete Colleagues: Implements the Colleague interface and communicates with the
Mediator and other objects through the Mediator.
The participants classes in this pattern are:
 Mediator - defines an interface for communicating with Colleague objects.
 ConcreteMediator - knows the colleague classes and keep a reference to the colleague
objects.
- implements the communication and transfer the messages between the colleague
classes
 Colleague classes - keep a reference to its Mediator object
- communicates with the Mediator whenever it would have otherwise communicated
with another Colleague.
Implementation
To implement the Mediator pattern, you need to do the following:
1. Define the Mediator interface, which will declare the methods that the objects will use to
communicate with the Mediator.
2. Create the Concrete Mediator, which will implement the Mediator interface and handle the
communication between the objects.
3. Define the Colleague interface, which will declare the methods that the objects will use to
communicate with the Mediator.
4. Create the Concrete Colleagues, which will implement the Colleague interface and
communicate with the Mediator and other objects through the Mediator.
Sample case study
Chat application
The chat application is another example of the mediator pattern. In a chat application we can have
several participants. It's not a good idea to connect each participant to all the others because the
number of connections would be really high, there would be technical problems due to proxies and
firewalls, etc... . The most appropriate solution is to have a hub where all participants will connect;
this hub is just the mediator class.
Participants:
 Chatroom(Mediator) - Defines the interface for interacting with participants
 ChatroomImpl (ConcreteMediator) - implements the operations defined by the Chatroom
interface. The operations are managing the interactions between the objects: when one
participant sends a message, the message is sent to the other participants.
 Participant(Collegue) - defines an interface for the participants.
 HumanParticipant, Bot (ConcreteCollegue) - implements participants; the participant can be
a human or a bot, each one having a distinct implementation but implementing the same
interface. Each participant will keep only a reference to the mediator.
Interpreter design pattern
Description
The Interpreter design pattern is a behavioral pattern that is used to define a grammar for a
language and then parse and interpret it. The pattern provides a way to evaluate sentences in a
language, specified by a grammar. The Interpreter pattern defines a way to interpret a language and
provides a way to evaluate sentences in the language. The pattern helps in separating the logic for
evaluating expressions from the logic for parsing expressions.
The Interpreter pattern is used when you have a language that you want to interpret and you want
to provide a way to evaluate sentences in the language. The Interpreter pattern is also useful when
you have a complex grammar that you want to parse and interpret. The Interpreter pattern can be
used in situations where there is a need to translate the statements in a specific language into
another language
Applicability
The Interpreter pattern should be used when:





You have a language to interpret and you want to provide a way to evaluate sentences in the
language.
You have a complex grammar to parse and interpret.
You want to provide a way to evaluate sentences in a language.
You want to separate the logic for evaluating expressions from the logic for parsing
expressions.
You want to translate the statements in a specific language into another language.
Structure
The Interpreter pattern typically includes the following components:





Abstract Expression: Defines an interface for evaluating an expression.
Terminal Expression: Implements an Abstract Expression and represents a leaf node in the
abstract syntax tree.
Nonterminal Expression: Implements an Abstract Expression and represents a non-leaf node
in the abstract syntax tree.
Context: Contains information that is required for the expression evaluation.
Client: Uses the Interpreter to parse and interpret the expressions.
Implementation
To implement the Interpreter pattern, you need to do the following:
1. Define the Abstract Expression, which will declare the interface for evaluating an expression.
2. Create the Terminal Expression, which will implement the Abstract Expression and represent
a leaf node in the abstract syntax tree.
3. Create the Nonterminal Expression, which will implement the Abstract Expression and
represent a non-leaf node in the abstract syntax tree.
4. Create the Context, which will contain information that is required for the expression
evaluation.
5. Create the Client, which will use the Interpreter to parse and interpret the expressions.
Sample case study
- Roman Numerals Convertor
The classical example fot the interpreter pattern is the one of interpreting the roman numerals. The
expresion to be interpreted is a string which is put in the context. The context consists of the
remaining unparsed Roman Numeral string and of the result of the numerral that are already
parsed. The context is passed to one of four sub-interpreters based on the type of
interpreting(Thousand, Hundred, Ten, One). This example it's using only TerminalExpressions.
The following participant classes are involved in this example: Context - keeps the current string that
has to be parsed and the decimal that contains the conversion already done. Initially the context
keeps the full string that has to be converted and 0 for the output decimal.
Expression - Consists of the interpret method which receives the context. Based on the current
object it uses specific values for Thousand, Hundred, Ten, One and a specific multiplier.
ThousandExpression, HundredExpression, TenExpression, OneExpression (TerminalExpression) Those classes are usued to define each specific expression. Ussualy, the TerminalExpression classes
implement the interpret method. In our case the method is already defined in the base Expression
class and each TerminalExpression class defines its behaviour by implmenting the abstract methods:
one, four(), five(), nine(), multiplier(). It is a template method pattern.
Main(Client) - In our litle example this class is responsible to build the syntax tree representing a
specific sentence in the language defined by the grammar. After the syntax tree is build the main
method is invoking the interpret method.
Download