Software Design Patterns

advertisement
Software Design Patterns
1
What is a design pattern?
1. It describes a general usable solution to a
recurring problem in an environment
2. It describes core of solution in a procedurallike structure
2
Why Design Patterns?
1. Simplifies object identification
2. Simplifies system decomposition
3. Proven & tested technique for problem
solving
4. Improves speed & quality of design /
implementation
5. Can be adapted / refined for specific system
under construction
3
Design Patterns Classification
Two categories
class scope:
relationship
between classes &
subclasses
statically defined at
run-time
object scope:
object relationships
(what type?)
Can be
manipulated at
runtime (so what?)
4
THE CONCEPT OF PATTERNS
Construction Architecture Patterns
The first idea of using patterns was for building
and proposed by the architect Christopher
Alexander.
He found recurring themes in architecture, and captured
them into descriptions
He called them patterns.
The term 'pattern' appeals to the replicated
similarity in a design
The similarity makes room for variability and customization
in each of the elements
Alexander defines: «Each pattern is a three part rule
which express a relation between a certain context, a
problem and a solution.
Each pattern is a relationship between
a certain context,
a certain system of forces which occurs
repeatedly in that context
a certain spatial configuration which allows these
forces to resolve themselves.
A pattern is an instruction and shows how this
configuration can be used over and over again.
The pattern is a thing that happens in the world
The rule which tell us how to create that thing and
when we must create it.
KitchenViewer Interface:
An architectural pattern example
Wall
cabinet
menu
Counter
display area
styles
Floor
cabinet
Modern
Classic
9
Antique
Arts & Crafts
KitchenViewer Example
Modern
Classic
Antique
10
Arts & Crafts
Selecting Antique Style
Modern
Classic
Antique
11
Arts & Crafts
Specific Design Purposes for
KitcherViewer
The procedure of rendering the various styles is
basically the same regardless of the style .
The code is as follows:
Counter counter =new Counter();
draw (counters);
A single block of code that executes in several possible
ways, depending on the context  Polymorphism
An application must construct a family of objects at runtime.
The design must enable choice among several families of
styles
An Introduction to Design Pattens
Example Application: Without applying a
Design Pattern
renderKitchen() method is used.
This code would have to be repeated for every style
The code that is supposed to be duplicated becomes
different in different places.
Example Application: Applying a Design Pattern
renderKitchen(myStyle) method is used
KitchenViewer design purpose is implemented by
applying Abstract Factory design pattern.
KitchenViewer Without Design Patterns
Client
renderKitchen()
Kitchen
WallCabinet
ModernWallCabinet
FloorCabinet
AntiqueWallCabinet
ModernFloorCabinet
14
AntiqueFloorCabinet
Abstract Factory Design Pattern
Properties
Provide an interface for creating families of related or
dependent objects without specifying their concrete
classes.
 A hierarchy that encapsulates: many possible
platforms, and the construction of a suite of products.
 The new operator considered harmful
Problem
If an application is to be portable, it needs to
encapsulate platform dependencies.
These platforms might include: windowing system,
operating system, database…
General
Structure
 The Abstract Factory defines a Factory Method per product.
 Each Factory Method encapsulates the new operator and
the concrete, platform-specific, product classes.
 Each platform is then modeled with a Factory derived class.
The Abstract Factory Idea
KitchenStyle
WallCabinet
getWallCabinet()
getFloorCabinet()
…
FloorCabinet
AntiqueWallCabinet
ModernKStyle
AntiqueKStyle
getWallCabinet()
getFloorCabinet()
getWallCabinet()
getFloorCabinet()
FloorCabinet getFloorCabinet()
{ return new ModernFloorCabinet(); }
…
AntiqueFloorCabinet
FloorCabinet getFloorCabinet()
{ return new AntiqueFloorCabinet(); }
17
Abstract Factory Design Pattern Applied to
Client
KitchenViewer
renderKitchen( KitchenStyle )
KitchenStyle
getWallCabinet()
getFloorCabinet()
Kitchen
getWallCabinet()
getFloorcabinet()
WallCabinet
FloorCabinet
ModernWallCabinet
ModernKStyle
getWallCabinet()
getFloorCabinet()
AntiqueKStyle
getWallCabinet()
getFloorCabinet()
AntiqueWallCabinet
ModernFloorCabinet
AntiqueFloorCabinet
18
Another Example
Factory Method
 Online bookstores that can choose different book distributors
to ship the books to the customers
 Both BookStoreA and BookStoreB choose which distributor
(EastCoastDistributor or MidWestDistributor or
WestCoastDistributor) to use based on the location of the
customer.
 This logic is in each bookstore's GetDistributor method.
Abstract Factory Pattern
The abstract factory design pattern is an
extension of the factory method pattern,
The abstract factory pattern allows to create
objects without being concerned about the
actual class of the objects being produced.
The abstract factory pattern extends the
factory method pattern by allowing more
types of objects to be produced.
Extension of GetDistributor() Method
to Abstract Factory Pattern
We can extend GetDistributor() method by
Adding another product that the factories can
produce.
In this example, we will add Advertisers that help the
bookstores advertise their stores online.
Each bookstore can then choose their own
distributors and advertisers inside their own
GetDistributor and GetAdvertiser method.
public void Advertise(IBookStore s)
{
IAdverister a = s.GetAdvertiser();
a.Advertise();
}
This allows to have client code (calling code) such as:
public void Advertise(IBookStore s)
{
IAdverister a = s.GetAdvertiser();
a.Advertise();
}
 Regardless if you pass in BookStoreA or BookStoreB
into the method, this client code does not need to be
changed since it will get the correct advertiser
automatically using the internal logics within the
factories.
 It is the factories (BookStoreA and BookStoreB) that
determines which advertiser to produce.
 The same goes for choosing which book distributor to
produce
UML of the Abstract Factory Design
Pattern
The Benefit of the Abstract Factory Pattern
 The benefit of the Abstract Factory pattern is that it
allows you to create a groups of products (the
distributors and the advertisers) without having to
know the actual class of the product being produced.
 The result is that you can have client code that does
not need to be changed when the internal logic of the
factories changed.
 We can change the types of the products (the
distributors and the advertisers) by changing the code
in the factories (the bookstores) without changing the
client code
public enum CustomerLocation { EastCoast, WestCoast }
class Program
{
static void Main(string[] args)
{
IBookStore storeA = new
BookStoreA(CustomerLocation.EastCoast);
Console.WriteLine("Book Store A with a customer from East Coast:");
ShipBook(storeA);
Advertise(storeA);
IBookStore storeB = new
BookStoreB(CustomerLocation.WestCoast);
Console.WriteLine("Book Store B with a customer from West Coast:");
ShipBook(storeB);
Advertise(storeB);
}
//**** client code that does not need to be changed ***
private static void ShipBook(IBookStore s)
{ IDistributor d = s.GetDistributor();
d.ShipBook();
}
//**** client code that does not need to be changed ***
private static void Advertise(IBookStore s)
{ IAdvertiser a = s.GetAdvertiser();
a.Advertise();
}
//the factory
public interface IBookStore
{
IDistributor GetDistributor();
IAdvertiser GetAdvertiser();
}
//concrete factory
public class BookStoreA : IBookStore
{
private CustomerLocation location;
public BookStoreA(CustomerLocation location)
{
this.location = location;
}
IDistributor IBookStore.GetDistributor()
{
//internal logic on which distributor to return /
/*** logic can be changed without changing the client code ****
switch (location)
{
case CustomerLocation.EastCoast:
return new EastCoastDistributor();
case CustomerLocation.WestCoast:
return new WestCoastDistributor();
}
return null;
}
IAdvertiser IBookStore.GetAdvertiser()
{
//internal logic on which distributor to return
//*** logic can be changed without changing the client code ****
switch (location)
{
case CustomerLocation.EastCoast:
return new RedAdvertiser();
case CustomerLocation.WestCoast:
return new BlueAdvertiser();
}
return null;
}
} //end of factory class
public class BookStoreB : IBookStore
//concrete factory
{ private CustomerLocation location;
public BookStoreB(CustomerLocation location)
{
this.location = location; }
IDistributor IBookStore.GetDistributor()
{ switch (location)
{ case CustomerLocation.EastCoast:
return new EastCoastDistributor();
case CustomerLocation.WestCoast:
return new WestCoastDistributor();
} return null; }
IAdvertiser IBookStore.GetAdvertiser()
{switch (location)
{ case CustomerLocation.EastCoast:
return new BlueAdvertiser();
case CustomerLocation.WestCoast:
return new RedAdvertiser();
}
return null; }
}
//the product
public interface IDistributor
{
void ShipBook();
}
//concrete product
public class EastCoastDistributor : Idistributor
{
void IDistributor.ShipBook()
{
Console.WriteLine("Book shipped by East Coast Distributor"); } }
//concrete product
public class WestCoastDistributor : IDistributor
{
void IDistributor.ShipBook()
{
Console.WriteLine("Book shipped by West Coast Distributor"); } }
public interface IAdvertiser //the product
{
void Advertise();
}
public class RedAdvertiser : IAdvertiser //concrete product
{
void IAdvertiser.Advertise()
{ Console.WriteLine("Advertised by RedAdvertiser"); } }
public class BlueAdvertiser : IAdvertiser //concrete product
{
void IAdvertiser.Advertise()
{ Console.WriteLine("Advertised by BlueAdvertiser");
}}
Download