SSE 658: Project I

burgerraraΛογισμικό & κατασκευή λογ/κού

18 Νοε 2013 (πριν από 3 χρόνια και 8 μήνες)

89 εμφανίσεις



SSE 658: Project I

Four

Design Patterns








Tom Glimmerveen

February 15, 2010

Design Patterns

Table of Contents

Observer Pattern

Explanation of the

Observer Pattern

Alternative Design

The Good and Bad about the Observer Pattern

Observer Design Pattern Implementation Example


The Factory Pattern

Explanation of the Factory

Pattern

Alternative Design

The Good and Bad about the
Factory

Pattern

The Factory

Pattern Implementation Example


The Singleton Pattern

Explanation of the

Singleton

Pattern

Alternative Design

The Good and Bad about the
Singleton

Pattern

Singleton

Design Pattern Implementation Example


Adapter Pattern

Explanation of
the
Adapter

Pattern

Alternative Design

The Good and Bad about the
Adapter

Pattern

Adapter

Design Pattern Implementation Example


The Wiki




Observer Pa
ttern

Explanation of
the
Observer Pattern


The observer design pattern describes a one
-
to
-
many relationship between a subject
object and its dependent observer objects. The subject object implements a subject interface
and notifies each observer (which implement the observer interface) ever time t
hat it has
changed state.
Observers may subscribe to a subject or unsubscribe from a subject. If they are
subscribed, they receive notifications

about the subject’s state changes
. If they are
unsubscribed, they stop receiving notifications.


The subject

is the owner of the data and so the observer objects are dependent on the
subject to inform them of its change in state. Subjects and observers are loosely coupled,
which helps with flexible OO design.

The design is considered flexible because an observ
er can
subscribe or unsubscribe to a subject during runtime. Also, new observers can easily subscribe
themselves by implementing the Observer interface and subscribing. Subject and Observer
classes can also chang
e without affecting one another and l
astly
, all a subject knows about its
observers is that they implement the observer interface; nothing more. All these principles
prove that the design is very flexible.


Data can be gathered after a notification in two different w
ays. The first way is called
“p
ushing”. This means that when the state of the subject changes, its notify observers method
passes
data

to the observers. Another way of approaching this is using the “pull” technique.
This means that when the notify observers method is called, the ob
servers

respond by

pull
ing

data from the subject class (usually via
public
get methods).
This technique allows observers to
only pull out the data they need; however, more public methods (the get methods) have to be
added to the subject class. Also, it i
s important in your design to never rely on the order the
observers are notified, as there are no guarantees that order will be consistent.


Alternative Design


Instead of using the observer design pattern, an alternative would have been to have an
ECM cla
ss object that gets data assigned to its variables from the sensors

(perhaps a private
getSensorData method)
. The classes that implemented the readout interface in this design
pattern would then, instead of being observers, pull the data
from the ECM obje
ct (using public
get methods) at specific

intervals.


The big problem with this design over using a su
bject and observers is that we have very
little design structure. When it comes to adding another observer to listen to the subject, it is
not as simple
as implementing an interface
.

Anytime a new class is “added” to the observer
list, it will have to have a get method in every place it needs a value from the subject.

Also, using this alternative design approach,

the “observers” don’t know when to get
the

data. Instead of being notified at each change by the
subject’s notifyObservers method, the
observer classes have to guess. Another option would be to have the “observers” only get the
data when it is
needed;

however, this causes unnecessary code to run
. If the value does not
change, or perhaps in a large for loop where there is little chance the values have changed, the
get method would have to be called each and every time the loop needs that value.


The Good and Bad about the Observer Pattern



One o
f the good things about observers is that subjects and observers can be added and
removed independent of each other. Also, subjects and observers know very little about one
another. This is good de
-
coupled OO design. Also, a subject knows nothing about
its observers
but simply broadcasts its state and that’s it.


The only disadvantage about the observer pattern is that when observers become
complex, it becomes difficult to figure out (for the programmer) what is going on and when an
observer is updated.


Observer Design Pattern

Implementation

Example


Shown below is the ECM program demonstrating the observer design pattern. The
subject interface is defined by ISubject, the observer interface is defined by IObserver, and the
IReadOut

interface is a common interface for readout devices in the car to implement. The
Speedo, Odometer, and Tach classes all implement the IReadOut interface and are observers of
the ECM object.

IReadOut calls for the display devices to
implement

a display m
ethod, the
IObserver interface requires an update method, and the ISubject interface requires a register,
unsubscribe, and notify observers method.


The register and unsubscribe methods in ECM allow an observer to be added to
the list of observers of the E
CM object and the notifyObservers method notifies all registered
observers when the state of the ECM object changes. If the state does not change by a large
enough amount, the observers are not notified. The update method is called

for each observer

once

the observers are notified of a change.


Shown below is all the code required to demonstrate the design pattern. The
readouts are set once and the observers are notified and call their display method. The ECM is
then set again, but not by a large enough

amount to warrant a notification. Lastly, the ECM is
updated one last time and the observers are again notified.




public

class

Main


{


public

static

void

Run()


{


ECM

ecm =
new

ECM
();
//create a new ECM (the subject)


Speedo

speedo =
new

Speedo
(ecm);
//create a speedometer,
tachometer, and odometer


Tach

tach =
new

Tach
(ecm);
//these objects are observers
(also called listeners)


Odometer

odometer =
new

Odometer
(ecm);




//think of this as if the ECM is reading in data from other
sensor



ecm.setSensorData(65, 3000, 15000);
//sets the input sensor data


ecm.setSensorData(66, 3010, 15000);
//doesn't change enough to
warrant a notification


ecm.setSensorData(68, 3100, 15001);
//the sensor data has changed
enough to notify the observers!


}


}


public

class

Odometer
:
IReadOut
,
IObserver


{


private

int

totalMiles;
//the odometer keeps track of the miles your
car

has been


private

ISubject

ecm;
//declare a local ecm object



public

Odometer(
ISubject

subject)


{


this
.ecm = subject;


ecm.registerObserver(
this
);
//registers the subject for this
observer


}



//called when the subject changes state


public

void

update()


{


ECM

ec = (
ECM
)ecm;


this
.totalMiles = ec.getTotalMiles();


display();
//displays a message every time it is called


}



public

void

display()


{


Console
.WriteLine(
"You have a total mileage of "

+ totalMiles +
"."
);


}


}


public

class

Tach
:
IReadOut
,
IObserver


{


private

int

rpms;
//the tachometer is responsible for displaying the
rpms


private

ISubject

ecm;
//declare a local ecm object



public

Tach(
ISubject

subject)


{


this
.ecm = subject;


ecm.registerObserver(
this
);
//registers the subject for this
observer


}



//called when t
he subject changes state


public

void

update()


{


ECM

ec = (
ECM
)ecm;


this
.rpms = ec.getRpms();


display();
//displays a message every time it is called


}



public

void

display()


{


Console
.WriteLine(
"Your revolutions per minute are "

+ rpms +
"."
);


}


}


public

class

Speedo
:
IReadOut
,
IObserver


{


private

int

speed;
//the speedometers job is to display the speed of
the car


private

ISubject

ecm;
//declare a local ecm object



public

Speedo(
ISubject

subject)


{


this
.ecm = subject;


ecm.registerObserver(
this
);
//registers the subject for this
observer


}



//called when the subject changes sta
te


public

void

update()


{


ECM

ec = (
ECM
)ecm;


this
.speed = ec.getSpeed();


display();
//displays a message every time it is called


}



public

void

display()


{


Console
.WriteLine(
"Your speed is: "

+ speed +
"."
);


}


}

//represents the engine control module


public

class

ECM
:
ISubject


{


//this is a List of the observers of this subject


private

List
<
IObserver
> observers;




//these are the values that are updated in this subject


private

int

speed;


private

int

rpms;


private

int

totalMiles;




//this value determines whether or not to notify the observers to
update


private

bool

changed;



public

ECM()


{


//instantiate observers List and set changed to false


observers =
new

List
<
IObserver
>();


changed =
false
;


}



//this adds an observer to the list of listeners


public

void

registerObserver(
IObserver

observer)


{


observers.Add(observer);


}



//this removes an observer from the list of listeners


public

void

removeObserver(
IObserver

observer)


{


observers.Remove(observer);


}



//this notifies all the observers to update as long as changed is
true


//the update is called as a response to the change in state of the
subject


public

void

notifyObservers()



{


if

(changed)


{


foreach

(
IObserver

obs
in

observers)


{


obs.update();


}


}


changed =
false
;


}



//if the sensors have sent
in new data and the data has varied
enough....


private

void

sensorDataChanged()


{


if

((
Math
.Abs(sentSpeed
-

this
.speed) > 2) || (
Math
.Abs(sentRpms
-

this
.rpms) > 50) || (
Math
.Abs(sentTotalMiles
-

this
.totalMiles)) > 1)


{


sentSpeed =
this
.speed;


sentRpms =
this
.rpms;


sentTotalMiles =
this
.totalMiles;


changed =
true
;


notifyObservers();


}


}



//simulates in
put from the sensor to the ECM


public

void

setSensorData(
int

speed,
int

rpms,
int

totalMiles)


{


this
.speed = speed;


this
.rpms = rpms;


this
.totalMiles = totalMiles;


sensorDataChanged();


}



//sets the changed flag to true


public

void

setChanged()


{


changed =
true
;


}




//gets the current RPMs stored in the ECM


public

int

getRpms()


{


return

rpms;


}



//gets the current total miles stored in the ECM


public

int

getTotalMiles()


{


return

totalMiles;


}



//gets the current speed stored in the ECM


public

int

getSpeed()


{


return

speed;


}


}


//interface for devices that display information to the driver


public

interface

IReadOut


{


void

display();


}


//interface for subjects to implement


public

interface

ISubject


{


void

registerObserver(
IObserver

observer);


void

removeObserver(
IObserver

observer);


void

notifyObservers();


}


//interface for observers to implements


public

interface

IObserver


{


void

update();


}

Console
Output:

Your speed is: 65.

Your revolutions per minute are 3000.

You have a total mileage of 15000.

Your speed is: 70.

Your revolutions per minute are 3300.

You have a total mileage of 15001.


The Factory Pattern

Explanation of the Factory Pattern



The
factory pattern allows us to practice the principle of “classes should be open for
extension, but closed for implementation.”

When the new keyword is used in a class, chances
are good that you’ll have to reopen
that class and make code changes later on.
By using the
factory pattern, you may encapsulate that object creation

code

in order to “close” the
client
class.
Factories are what
handle

this

object creation.

Subclasses are used to encapsulate the
object creation code in a factory method, which is ca
lled in the client code (usually the
superclass). This method is usually defined abstractly in the superclass and then implemented
in one or more subclasses. Factory methods are often parameterized in order to select
amongst numerous variations of creati
ng an object (or product).


The idea is to pull out

(encapsulate)

what varies. In example, if you have a hamburger
restaurant

chain where each store

sells different types of
burgers.


Y
ou can see that what varies
is the type of hamburger
each

store crea
tes.

The way the burgers

are cooked and served does
not change.

To use the factory pattern in this situation, you can pull out the method that
creates a particular type of hamburger and leave the cooking and serving methods the same.
D
oing this allows e
ach hamburgerS
tore
subclass (bbq
Store, cajunStore
, etc.
) to decide how
their own

hamburgers are made.

In this situation, the createHamburger method will be
defined as an abstract method in the hamburgerStore class

(which will also be made abstract)

and defined concretely in each of its subclasses.
These factory methods will typically return a
product that will be used in the superclass (i.e hamburgerStore). These factory methods isolate
the superclass (client) from knowing exactly what object is b
eing created.


These p
roducts that are created by our factory meth
ods are generally defined by a
p
roduct with numerous subclasses. For our Hamburger class, which is the
abstract
object type
of which its subclasses are
passed back from our factory methods
in our different concrete
store objects, we have a bbqHamburger, cajunHamburger, etc. In our hamburgerStore
superclass, we’ll declare a Hamburger object and instantiate it with the createHamburger
method.

This method is defined within each subclas
s of t
he abstract hamburgerStore

class and
thus, is defined by what type of
hamburgerStore

is being used.

If we are using a
bbqHamburgerStore object, it will create a bbqHamburger

from the createHamburger method
.

If a type is specified as a parameter for the c
reateHamburger method, then a bbqHamburger of
that particular type will be created. For example, if we called
bbqHamburgerStore.createHamburger(“cheddar”) for our method call, we will get back a new
bbqCheddarHamburger. If the program does not have speci
fic types that can be entered, then
we would just call bbqHamburgerStore.createHamburger() and get back a new bbqHamburger
object.

Since the createHamburger method in the abstract hamburgerStore

class is set equal to
a Hamburger object (abstract class), the client never really knows what type of Hamburger it is
dealing with.
This hides the exact type of hamburger

from the methods in

hamburgerStore.
This doesn’t matter though, since these method
s are meant to work with the Hamburger class,
which each different type of hamburger inherits from.
In our example, we call the
hamburgerStore and its subclasses our “creator classes”

and we call our H
amburger class and
its subclasses our “product classes
”.


Alternative Design



The alternative way to create a hamburgerStore, without using the factory pattern,
would be to conditionally instantiate different types of hamburgers within the subclasses of our
hamburgerStore

class. First, we would check a parameter (maybe a string) and see what type
of hamburger has been ordered: a bbq cheese burger, a cajun onion burger, etc. Then within
these classes, we would call a burger = new cheese burger method that would create the

particular style of hamburger for that order. Each particular store may have 10 different types
of burgers they sell. Using all these new keywords in our client code makes the class
susceptible to future alterations. If a new style hamburger is created
, we have to add another
class to our solution as well as add more instantiations and conditions

to our code (and
everywhere else the burger type is conditionally checked). This doesn’t follow the principle of
close
d

for modification, open for extension.


By using the factory pattern, we may simply create
a new store subclass and new hamburger subclass and keep our client code the same.


The Good
and Bad

about the Factory

Pattern



One of the great parts of this design is it de
-
couples the creation of a pr
oduct from its
use. This is great when future plans require you need to add more hamburger stores. All the
code will stay the same and the programmer only needs to create a new type of hamburger
that extends the hamburger class and a new hamburgerStore w
hich creates that type of
hamburger in its createHamburger method. From that point, the new type of hamburger can
be used in all the inherited methods from the hamburgerStore class.

This pattern makes it easy
for third parties to add functionality to a p
rogram.

The bad of this is that you
have to

create
two classes to create a new product.


Also, this design helps avoid duplicate code by creating one place to perform changes.
S
ince concrete subclasses are used to create objects, the client code can depe
nd on an
interface and not an implementation (
think the “
new
” keyword
). This allows the class to be
open for extension (i.e, adding more subclasses), but close form modification.

This makes the
code much more flexible for later changes.


Factory Pattern

Implementation

Example





public

static

class

Main


{


public

static

void

Run()


{


//create a cajunHamburgerStore and bbqHamburgerStore


cajunHamburgerStore

cStore =
new

cajunHamburgerStore
();


bbqHamburgerStore

bbqStore =
new

bbqHamburgerStore
();



//create a hamburger at each store


Hamburger

hamburger1 = cStore.makeBurger();


Hamburger

hamburger2 = bbqStore.makeBurger();



//output the burgers that
were made


Console
.WriteLine(
"
\
n"

+ hamburger1);


Console
.WriteLine(hamburger2);


}


}



public

abstract

class

hamburgerStore


{


Hamburger

burger;



public

Hamburger

makeBurger()


{


burger = createHamburger();


burger.prepare();


burger.cook();


burger.serve();


return

burger;


}



//the createHamburger class will be overrided in this class's
subclasses


public

abstract

Hamburger

createHamburger();


}



public

class

bbqHamburgerStore
:
hamburgerStore


{


//override the abstract hamburgerStore's createHamburger method


public

override

Hamburger

createHamburger()


{


return

new

bbqHamburger
();


}


}



public

class

cajunHamburgerStore
:
hamburgerStore


{


//override the abstract hamburgerStores's createHamburger method


public

override

Hamburger

createHamburger()


{


return

new

cajunHamburger
();


}


}



public

abstract

class

Hamburger


{


//create Hamburger characteristics


public

string

name;


public

string

buns;


public

string

temp;


public

List
<
string
> toppings =
new

List
<
string
>();



public

void

prepare()


{


Console
.WriteLine(
"Adding toppings..."
);


foreach

(
String

topping
in

toppings)


Console
.WriteLine(topping.ToString());


}



public

void

cook()


{


Console
.WriteLine(
"Cooking to "

+ temp);


}



public

void

serve()


{


Console
.WriteLine(
"Serving hamburgers"
);


}



public

string

getName()


{


return

name;


}



public

override

string

ToString()


{


return

temp +
" "

+ name;


}


}



public

class

bbqHamburger
:
Hamburger


{


//constructor for the bbqHamburger subclass


public

bbqHamburger()


{


name =
"BBQ Burger"
;


buns =
"Wheat Bread"
;


temp =
"Medium
-
Well"
;


toppings.Add(
"BBQ Sauce"
);


toppings.Add(
"Bacon"
);


}


}



public

class

cajunHamburger
:
Hamburger


{


//constructor for the cajunHamburger subclass


public

cajunHamburger()


{


name =
"Cajun Burger"
;


buns =
"White Bread"
;


temp =
"Medium
-
Well"
;


toppings.Add(
"Cajun Spices"
);


}


}


Console Output:

Adding toppings...

Cajun Spices

Cooking to Medium
-
Well

Serving hamburgers

Adding toppings...

BBQ Sauce

Bacon

Cooking to Medium
-
Well

Serving hamburgers


Medium
-
Well Cajun Burger

Medium
-
Well BBQ Burger


Singleton Pattern

Explanation of t
he
Singleton Pattern


The singleton pattern allows just a single instance of a class to be instantiated. This is
done by making the constructor of a class private and instantiating it only one time. This single
instance
is defined as a static object within
the class and
can be accessed globally from a getter
method within the class

(usually called getInstance)
.


A big obstacle to look out for with the singleton pattern is issues with multithreading. If
numerous threads are used, the class can be instantiated statically (right away) or its
getInstan
ce method can be synchronized.

Instantiating the instance statica
lly works great if
you know that you will need to instantiate the object in your code no matter what. Using just
the synchronize keyword in the method name is generally not a good idea as it creates a lot of
overhead if the instance is used often. A good

solution to this is the double
-
checked lock
implementation.

Another way of handling it may be to use a double
-
checked lock implementation.
This
checks within the getInstance code whether or not the object is null. Then Singleton.class is
synchronized an
d lastly, the instance is checked against null again. If the object is null, a new
instance of the object is created. If it is not null, then the instance of the object is created.

Other things to watch out for are more than one class loader, which could

end up with
more than one instance of the singleton. Also, using versions of java prior to java 1.2 could
result in the singleton instance being garbage collected through a bug in the garbage collector.

The singleton pattern can be useful whenever an obj
ect needs to be used globally, but
should not

be instantiated more than one time.
Examples of this type of information may be
registry information,
thread pools
,

caches,

etc.


Alternative Design


A way to have a global access point other than using the si
ngleton pattern is to use
global variables. The issue with these
is that you cannot prevent the class from being
instantiated just one time. If more than one instantiation were to occur, different versions of
the object may contain different data, which
would result in big problems with the code.


The Good and Bad about the Singleton Pattern


A bad part about the singleton pattern is its possibility of being overused. Too many
singletons used in a program (too many global variables) can be bad news.

Als
o, if the
programmer were to have to make any changes in the singleton class, every piece of code
dependent on the singleton instance would have to be changed.

The pattern can be great
however for

a logging service,

defining configuration information, reg
istry information, or cache
files.


Singleton Pattern Implementation Example


In the very simple example below, a class accesses the singleton instance to show how
simple it is to pull values globally

from the instance
.
The Singleton class is given a single,
private, static instance which is immediately instantiated. This single instance can be accessed
via a public property, Instance, within the class. The singleton constructor is kept private to
keep the class from be
ing instantiated more than once. This is certainly not the only way of
creating a singleton but, is one of the easier ways. The console output at the bottom shows
that the Main class was able to access the myNumber and myName variables from the
singleton
.



public

sealed

class

Singleton


{


//here we immediately declare our singleton to help stay thread safe


private

static

Singleton

instance =
new

Singleton
();



//here are two unimportant variables representing cache files or
r
egistry information


public

int

myNumber = 5;


public

string

myName =
"Singleton Instance!"
;



//making the constructor private keeps the class from being
instantiated more than once


private

Singleton()


{




}



//here is the public property we can get at our single instance from


public

static

Singleton

Instance


{


get


{


return

instance;


}


}


}



public

class

Main


{


public

static

void

Run()


{


int

var =
Singleton
.Instance.myNumber;


string

var2 =
Singleton
.Instance.myName;


Console
.WriteLine(var +
", "

+ var2);


}


}

Console Output:

5, Singleton
Instance!


Adapter Pattern

Explanation of the Adapter Pattern


The adapter pattern is a design pattern use
d

to convert one object implementing an
interface

into another inheritor of a different interface
.

A simpler way to think about it is that
an adapter converts one interface into another.
This is done in order to convert one class
implementing a certain interface into another interface that i
s expected in the client code. In
code, this is done by havin
g an adapter class which implements a target interface. This class is
composed with an object that is of the type of interfa
ce that needs to be converted.

Looking at the example section,

we can see that the adaptee

is converted to implement
the

target

int
erface

via the adaptor.

This means that the client and the adaptee are decoupled,
which is great OO design. The client is expecting the target interface, not the interface the
adaptee is implementing; therefore, the adaptor is necessary.

Also, this patt
ern involves the
client being dependent on an interface, and not an implementation, which is also great OO
programming.

So far all that we’ve talked about is object adapters, but another form of adapters exists
called “class adapters.” These adapters can
only be used in languages, unlike C# or Java, where
you may extend more than one class. This allows an adapter to extend the adaptee and target.
This makes it easy because you can override since you inherit from each class.

There are also adapters that e
xist called “Two Way Adapters.” These adapters
implement both interface involved (target and adaptee’s interface), which allows the interface
to work in both directions.

Lastly, I felt it important to briefly mention another pattern. This pattern
is simi
lar to
the adapter pattern, but is used for simplification rather than conversion. This pattern is called
the “Façade Pattern.” This pattern is simply a class that is, by composition, able to greatly
simplify a subsystem of more complex classes. For exa
mple, suppose you have an airplane full
of different avionic controls and systems.

It would
not only

be

tedious, but very difficult to
individual
ly

control and turn on each and every system and set it to its appropriate settings.
The Façade pattern allow
s you to simply click an, “air plane on” button

or a “start engines”
button
. This class is composed of all the objects necessary to provide the function of starting
the airplane

or the engines and all the appropriate methods are put inside the single “sta
rt
engines” method in the facade
. This
abstracts the pilot from all the more detailed controls but,
doesn’t keep them from being accessible. If the pilot chooses to tweak some of the details on
his own, he may still do so.


Alternative Design


Another wa
y of implementing an adaptor would be to alter the client side code to allow
for different objects to be passed in. This could be done by creating overloaded methods, each
of which taking in a different type of object and
operating on it for that particul
ar object.
This
design is less than optimum however,

as

it requires double the necessary methods each time a
new object needs to be “adapted.”


The Good and Bad about the Adapter Pattern


The adaptor pattern is excellent due to its decoupled design. The client and the adaptee
are kept unknowing of each other. When the adaptor is used, the client methods don’t know
the difference between it and any other objects that are already impl
ementi
ng the target
interface.


The adapter pattern also makes maintenance much simpler if you expect the interface
to change in the future. Instead of having to alter all the client code, you may create (or
rework) an adapter class to keep from having to modif
y the client code.


Adapting to a larger interface can impose some difficulties however, chances are that it
will take you less time and effort to create an adaptor class and leave the adaptee and client
code unmodified. The only other option would be to
rework the client side method calls

to
incorporate inheritors of the

new interface
, which would be difficult and also require more
dependence in the client code on different objects.


Adapter Design Pattern Implementation Example


In this example, an adapt
ee object is “wrapped”

in an adapto
r in order to have it
implement the target interface, which can then be used in the client

code
.
The console output
is shown below the code. The client creates an ITarget object and an IAdaptee object and runs
it throug
h the DoStuff method. The ITarget is instantiated as a new Target object and is passed
through the method with a problem. The IAdaptee object is set to be a new Adaptee, which
does not implement the interface the DoStuff method expects as a parameter.
T
he Adaptor
allows us to wrap the Adaptee object and pass the new Adaptor object in as a parameter to the
DoStuff method (since it implements ITarget). The only issue that arises is when the
targetMethod is called, which results in an exception since the A
daptor class could not convert
it for the adaptee object.




public

static

class

Client


{


public

static

void

Run()


{


//creates a new Target object


ITarget

iTarget =
new

Target
(
"target!!"
);


doStuff(iTarget);



//creates a new Adaptee object and runs it through the client
method "doStuff"


IAdaptee

iAdaptee =
new

Adaptee
(
"adaptee!!"
);


//creates an adaptor that wraps the iAdaptee


Adaptor

adaptedAdaptee =
new

Adaptor
((
Adaptee
)iAdaptee);


doStuff(adaptedAdaptee);


}



private

static

void

doStuff(
ITarget

targ)


{


Console
.WriteLine(
"I've got a Target!: "

+ targ.getName());
//so
it thinks!


Console
.WriteLine(
"Similar method: "

+
targ.oneSimilarMethod(10));
//this method was able to be adapted


targ.targetMethod();
//throws a not implemented exception for
adapteees being converted by adaptor


}


}



public

c
lass

Adaptee
:
IAdaptee


{


//private name of the adaptee


private

string

name;



//constructor for the Adaptee, which sets the object's name


public

Adaptee(
string

name)


{


this
.name = name;


}



//a method only the adaptee uses


public

void

adapteeMethod()


{


Console
.WriteLine(
"Do some adaptee stuff"
);


}



//A method that can be adapted to being used when implementing the
ITarget interface


public

int

twoSimilarMethod(
int

val)


{


return

5 + val;


}



//A method both IAdaptee and ITarget have in common


public

string

getMyName()


{


return

name;


}


}



//interface
implemented by Adaptee


public

interface

IAdaptee


{


void

adapteeMethod();


int

twoSimilarMethod(
int

val);


string

getMyName();


}



//interface implemented by Target


public

interface

ITarget


{


void

targetMethod();


int

oneSimilarMethod(
int

val);


string

getName();


}



public

class

Adaptor
:
ITarget


{


//must declare an object to be wrapped/converted


IAdaptee

adaptee;



//constructor that passes in the
adaptee to be converted


public

Adaptor(
Adaptee

adaptee)


{


this
.adaptee = adaptee;


}



//cannot implement targetMethod with an adaptee, so we throw a not
implemented exception


public

void

targetMethod()


{


throw

new

NotImplementedException
();


}



//we are able to adapt this method from IAdaptee to ITarget


public

int

oneSimilarMethod(
int

val)


{


return

1 + val;


}



//this method is

easily adapted as both interfaces have similar get
name calls


public

string

getName()


{


return

adaptee.getMyName();


}


}



public

class

Target
:
ITarget


{


//private name of the target


private

string

name;



//constructor that sets the object's name


public

Target(
string

name)


{


this
.name = name;


}



//a method only the target is able to do


public

void

targetMethod()


{


Console
.WriteLine(
"do some target kinda method"
);


}



//a method that can be converted


public

int

oneSimilarMethod(
int

val)


{


return

1 + val;


}



//another method that can be easily converted


public

string

getName()


{


return

name;


}


}


Console Output:

2008
\
Projects
\
AdapterPatternExample
\
AdapterPatternExample
\
bin
\
Debug
\
AdapterPatternExample.exe',
Symbols loaded.

I've got a Target!: target!!

Similar method:

11

do some target kinda method

I've got a Target!: adaptee!!

Similar method: 11

A first chance exception of type 'System.NotImplementedException' occurred in
AdapterPatternExample.exe


The Wiki


This is the starting s
creen

that you see right when you create a wiki
-
space. This page
can be edited by clicking the edit button in the top right of the horizontal toolbar (in light blue).
This toolbar also gives you access to the discussion page, history page, and notify me page.

The
discussion page Is a simple discussion board, the history page documents the changes made to
the wiki and by whom, and the notify me page gives you the ability to get notifications by email
when edits are made or discussions are posted.

On the vertic
al toolbar, you may create a new wiki page, view recent changes, or access
the manage wikis menu. This menu is full of options that include member permissions, the
page’s look and feel, and many more tools. Below the manage wikis button, all the pages of

the
wiki are available to click.




Below is the edit menu, which shows whichever page you clicked the edit button on.
This toolbar at the top of the page appears and gives you the ability to change what text you
input, put in pictures, add links to the

pages, widgets, etc. These widgets include RSS feeds,
polls, calendars and more.




The widgets drop
-
down menu option is shown below. The image shows below that
showns the manage wikis option.





In the edit wikis section of this report, I found
the interfacing very simple to follow.
Everything was very intuitive in making a wiki page. I look forward to working more with it for
the third project. I do intend to post links to my projects on the wiki page as well as the FTP site
for ease of acces
s to others.