Your SlideShare is downloading. ×

Design patterns


Published on

1 Like
  • Be the first to comment

No Downloads
Total Views
On Slideshare
From Embeds
Number of Embeds
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

No notes for slide


  • 1. Design Patternswith PHP5Outreach Technology - Office of Information TechnologyJason AustinSenior Solutions Implementation Engineerjason_austin@ncsu.eduGarrison LockeLead Dynamic Functionality
  • 2. Why are you here?Specific project you are working on?Just curious?Our tractor-beam of PHP goodness?
  • 3. Why are we here?We were “LOST”No real-worldexamples
  • 4. This presentation will...... introduce several design patterns... tell you how they work... tell you why you would want to use them... show you actual code in a working example
  • 5. Before we begin...You should have a working knowledge ofobject oriented principlesWe will be using PHP5 as our language ofchoiceSlides are available on ClassMate at
  • 6. OverviewDesign PatternsHistoryExamplesArchitectural PatternsExamples
  • 7. Design Patterns
  • 8. History of Design PatternsOriginated as architectural concept byChristopher AlexanderA Pattern Language: Towns, Buildings,Construction - 1977Inspired the Design Pattern movement
  • 9. What is a design pattern?If there was a problem,Yo! I’ll solve it...Checkout the hook,while my DJ revolves it.- Robert Van Winkle (Vanilla Ice)
  • 10. Ice Ice Baby -Programmers RemixIf you got a programming problem,Yo! Someone’s solved it...Checkout these patterns,And they’ll help ya resolve it.- The smooth stylings of Outreach Technology
  • 11. Fo’ serious...General reusable solution to a commonproblemShow relations and interactions betweenobjectsSpecifically deal with software design
  • 12. Design patterns are NOT...... related to Vanilla Ice... specific pieces of code... algorithms... programming language-specific
  • 13. Why use design patterns?“Do you understand the words that are comin outta my mouth?“
  • 14. Why use design patterns?“If you ain’t first, you’re last”
  • 15. Why use design patterns?“You are not special. You are not a beautiful or unique snowflake.”
  • 16. Where do I start?Before using a design pattern, you must ...... understand your problem... understand the pattern... understand how the pattern solves yourproblem
  • 17. Design Pattern Myths“Because I used a designpattern, my code is welldesigned.”“Using a design pattern isalways best.”“If I use a design pattern, Iwill be as awesome asJason and Garrison.”
  • 18. Gang of Four (GoF)“Design Patterns: Elements of Reusable Object-Oriented Software” - ISBN 0-201-63361-2Erich GammaRichard HelmRalph JohnsonJohn Vlissides
  • 19. GoF CategoriesCreationalStructuralBehavioral
  • 20. Creational DesignPatterns
  • 21. Creational Design PatternsDeal with class instantiationControls how objects are createdExample PatternsAbstract FactorySingletonPrototype
  • 22. Abstract Factory
  • 23. Abstract FactoryFactory method defines what functions mustbe available in each factoryThe factory used is dependent on a singlevariablePolymorphism FTW!
  • 24. How’s it work?An abstract class is created with a collection ofmethodsMultiple worker classes are created thatimplement the abstract classAbstractClassWorker ClassWorker ClassWorker Class...
  • 25. How’s it work?The client requests a new objectThe Factory, using logic, returns a new instanceof the correct worker classesClient FactoryWorker ClassWorker ClassWorker Class...
  • 26. Why would I use this?Single function call to get any type of classLet’s the logic live in a single place (Factory)Easy to add additional logic later
  • 27. Problem:You need to write an application which can createthumbnails of images. Any type of image can bepassed.
  • 28. Solution: Abstract Factory<?phpabstract class ImageReaderAbstract{abstract function readImage($image);}class ImageReaderJpg extends ImageReaderAbstract{public function readImage($image){//do magic to read jpgreturn $image;}}class ImageReaderGif extends ImageReaderAbstract{public function readImage($image){//do magic to read gifreturn $image;}}....
  • 29. Solution: Abstract Factory<?phpclass MyImageFactory{public function getReader($image){$imageType = $this->getImageType($image);$reader = null;switch ($imageType) {case ‘jpg’:$reader = new ImageReaderJpg();break;case ‘gif’:$reader = new ImageReaderGif();break;default:die(‘image type not defined’);}return $reader;}...}$factory = new MyImageFactory();// Return ImageReaderJpg() instance$image1 = $factory->getReader($someJpeg);// Return ImageReaderGif() instance$image2 = $factory->getReader($someGif);
  • 30. Singleton
  • 31. Singleton“There can be only one!”
  • 32. How’s it work?Define a classOverwrite its ability to create new instances ofitself or to clone itselfProvide interface to create a single instance ofitself, then return that single instance when it’scalled again.
  • 33. Why would I use this?Keep overhead lowIE: Database ConnectionsEnsure all calls from a client interact with thesame object, preventing data inconsistency
  • 34. Problem:Your application requires you to access certainobjects and variables from multiple classes.Because of the issues with using globalvariables, you want to implement a registry.
  • 35. Rant: Why not globals?<?php$myVar = ‘Hello World’;testGlobal();function testGlobal(){// Produces an error because $myVar is undefinedecho $myVar;// imports $myVar into the local scopeglobal $myVar;// now this works!echo $myVar;}Reusing parts of the script is impossibleTracing the code is much harderUnderstanding the code later is harder
  • 36. Security ImplicationsIn PHP <= 5.0.5, it is possible to overwrite theglobal space from outside whenregister_globals is turned onAllow for SQL injection attacks and executionof arbitrary PHP code
  • 37. Registry PatternAllows the storing and retrieval of data (andobjects) which need to be accessed globallyCan be a Singleton, but doesn’t have to be
  • 38. Back to the Problem:Your application requires you to access certainobjects and variables in multiple classes.Because of the issues with using globalvariables, you want to implement a registry.
  • 39. Solution: Singleton<?phpclass Registry{private static $_instance = null;private $_data = array();private function __construct() {}private function __clone() {}public static function getInstance(){if (is_null(self::$_instance)) {self::$_instance = new self;}return self::$_instance;}public function set($var, $val){$this->_data[$var] = $val;}public static function get($var){return $this->_data[$var];}}
  • 40. Solution: Singleton<?phpclass myObject{public function __construct(){$registry = Registry::getInstance();$registry->set(‘myVar’, ‘test’);}}$obj = new myObject();$registry = Registry::getInstance();$myVar = $registry->get(‘myVar’);echo “myVar is set to “ . $myVar;?>myVar is set to test
  • 41. Registry v/s Globals<?php$registry = Registry::getInstance();$registry->set(‘includePath’, ‘/inc/path’);class myObject(){public function __construct(){$registry = Registry::getInstance();include_once($registry->get(‘includePath’) .‘/include.php’;}}// will include ‘/inc/path/include.php’$obj = new myObject();<?php$includePath = ‘/inc/path’;class myObject(){public function __construct(){include_once($GLOBALS[‘includePath’] .‘/include.php’;}}// will include ‘/inc/path/include.php’$obj = new myObject();
  • 42. Registry v/s Globals<?php$registry = Registry::getInstance();$registry->set(‘includePath’, ‘/inc/path’);class myObject(){public function __construct(){$registry = Registry::getInstance();include_once($registry->get(‘includePath’) .‘/include.php’;}}// will still include ‘/inc/path/include.php’$obj = new myObject();<?php$includePath = ‘/inc/path’;class myObject(){public function __construct(){include_once($GLOBALS[‘includePath’] .‘/include.php’;}}// will include ‘’$obj = new myObject();
  • 43. Duplicating Singleton<?php$registry = Registry::getInstance();// Throws an exception as well$newRegistry = clone $registry;<?php// Throws an exception...don’t do it this way!$registry = new Registry();
  • 44. Prototype
  • 45. PrototypeCreate new objects from cloning an existingobject (the prototype)
  • 46. How’s it work?Create a standard object(the prototype)Clone that object to createnew instances
  • 47. Why would I use this?Less resource intensive than creating newobjectsGood when you don’t know theimplementation details of the original object
  • 48. Problem:You are writing an application for a veterinaryhospital which deals with lots of dogs and cats.
  • 49. Answer: Prototype<?phpabstract class AnimalPrototype {protected $species;protected $type;abstract function __clone();public function getSpecies(){return $this->species;}public function getType(){return $this->type;}public function setType($type){$this->type = $type;}}?><?phpclass DogPrototype extends AnimalPrototype {public function __construct(){$this->species = ‘Canine’;}public function __clone(){}}class CatPrototype extends AnimalPrototype {public function __construct(){$this->species = ‘Feline’;}public function __clone(){}}?>
  • 50. Answer: Prototype<?php$dogPrototype = new DogPrototype();$catPrototype = new CatPrototype();$fido = clone $dogPrototype;$fido->setType(‘Border Collie’);$spot = clone $dogPrototype;$spot->setType(‘Lab’);$fluffy = clone $catPrototype;$fluffy->setType(‘Tabby’);echo “Fido is a “ . $fido->getSpecies() . “ that is a “ . $fido->getType() . “.<br />”;echo “Spot is a “ . $spot->getSpecies() . “ that is a “ . $spot->getType() . “.<br />”;echo “Fluffy is a “ . $fluffy->getSpecies() . “ that is a “ . $fluffy->getType() . “.<br />”;?>Fido is a Canine that is a Border Collie.Spot is a Canine that is a Lab.Fluffy is a Feline that is a Tabby.
  • 51. Structural DesignPatterns
  • 52. Structural Design PatternsIdentify how objects relate to each otherExample PatternsAdapterCompositeDecorator
  • 53. Adapter Pattern
  • 54. Adapter PatternAlso referred to as the “Wrapper Pattern”Converts the interface of one class to be whatanother class expects
  • 55. How’s it work?Create a class with some functionalityCreate another class (the adapter) that is awareof the original classes functionality, and thenimplements it’s ownQuery the adapter to retrieve informationabout the original class
  • 56. Why would I use this?Allows interactivity between classes thatnormally would be incompatibleAbstracts methodology away from your clientclass
  • 57. Problem:You are writing an application that requires youto access a database. You want to be flexible inyour approach so that any type of database canbe used without changing much functionality inyour code
  • 58. Solution: Adapter<?phpinterface AdapterInterface{public function __construct($u, $p, $h, $d);public function select($query);}class MysqlAdapter implements AdapterInterface {protected $_link = null;public function __construct($u, $p, $h, $d){$this->_link = mysql_connect($h, $u, $p);mysql_select_db($d);}public function select($query){return mysql_query($query, $this->_link);}}<?phpclass Database {protected $_db;public function __construct(AdapterInterface $db){$this->_db = $db;}public function fetch($query){return $this->_db->select($query);}}
  • 59. Solution: Adapter<?php$myConnection = new MysqlAdapter(‘user’, ‘password’, ‘’, ‘my_database’);$db = new Database($myConnection);$query = “SELECT * FROM tbl_users”;$result = $db->fetch($query);
  • 60. Composite Pattern
  • 61. Composite PatternAllows an application to treat an individualobject and a collection of those objects thesame
  • 62. Composite PatternContains 3 basic partsComponentLeafCompositeWikipedia
  • 63. Composite: ComponentImplements defaultbehavior for all classesDetermines interface foreach componentImplements defaultbehavior if required
  • 64. Composite: LeafRepresents end-points inthe compositionImplements theComponent class,defining the primitivebehavior
  • 65. Composite: CompositeDefine behavior forcomponents that havechildrenStores the childrenImplements theComponent class
  • 66. How’s It Work?Create a classContains all functionality needed, whether itis a leaf or a compositeCreate multiple instances of the classAssign the classes to each other in a tree-likemanor
  • 67. Why would I use this?Great way to deal with tree-structured dataDon’t have to discriminate between leafs andbranches
  • 68. Problem:You are creating an application to manageemployees in a company. Within that company,there is a hierarchy of managers and employees.
  • 69. Solution: Composite<?phpclass Employee {protected $_name = ‘’;protected $_subordinates = array();public function __construct($name){$this->_name = $name;}public function getName(){return $this->_name;}public function addSubordinate(Employee $subordinate){$this->_subordinates[] = $subordinate;}public function removeSubordinate($position){unset($this->_subordinates[$position]);}public function getSubordinate($position = null){if (is_null($position)) {return $this->_subordinates;}return $this->_subordinates[$position];}public function hasSubordinates(){return (count($this->_subordinates) != 0);}}
  • 70. Solution: Composite<?php$bob = new Employee(‘Bob’);$frank = new Employee(‘Frank’);$sue = new Employee(‘Sue’);$jess = new Employee(‘Jess’);$larry = new Employee(‘Larry’);$bob->addSubordinate($frank);$bob->addSubordinate($sue);$jess->addSubordinate($bob);$jess->addSubordinate($larry);echo $jess->getName() . ‘ has these subordinates:<br />’;echo processSubordinates($jess);function processSubordinates(Employee $e) {$subordinates = $e->getSubordinate();$str = ‘<ul>’;foreach ($subordinates as $s) {$str .= ‘<li>’ . $s->getName() . ‘</li>’;if ($s->hasSubordinates()) {$str .= processSubordinates($e);}}$str .= ‘</ul>’;return $str;}Jess has the following subordinates:•Bob•Frank•Sue•Larry
  • 71. Decorator Pattern
  • 72. Decorator PatternAllows new or additional behavior to beadded to an existing class dynamicallyDifferent from subclassingSubclassing would add the functionality toall instances of an objectA decorator can add functionality to asingle instance of an object
  • 73. How’s it work?A concrete class is createdA standard decorator class (or interface) is created,which has knowledge of the concrete classAdditional decorators are created that extend thefunctionality of the standard decoratorThe client uses the decorators to do different thingsto the concrete class
  • 74. Why would I use this?Add responsibilities to individual objects, notan entire classBecause functionality can be added to anindividual object and not the whole class, youhave less overhead
  • 75. Problem:You are writing an application where you wantto display user’s name in different ways.
  • 76. Solution: Decorator<?phpclass Person {protected $_name = ‘’;public function __construct($name){$this->_name = $name;}public function getName(){return $this->_name;}}<?phpclass PersonDecorator {protected $_person = null;public function __construct(Person $person){$this->_person = $person;}public function showName(){return $this->_person->getName();}}
  • 77. Solution: Decorator<?phpclass PersonBoldDecorator extends PersonDecorator {public function showName() {return “<b>” . parent::showName() . “</b>”;}}class PersonItalicsDecorator extends PersonDecorator {public function showName() {return “<i>” . parent::showName() . “</i>”;}}class PersonUnderlineDecorator extends PersonDecorator {public function showName() {return “<u>” . parent::showName() . “</u>”;}}
  • 78. Solution: Decorator<?php$randy = new Person(‘Randy Randyface’);$b = new PersonBoldDecorator($randy);$i = new PersonItalicsDecorator($randy);$u = new PersonUnderlineDecorator($randy);echo “Bold: “ . $b->showName() . “<br />”;echo “Italics: “ . $i->showName() . “<br />”;echo “Underline: “ . $u->showName() . “<br />”;?>Bold: Randy RandyfaceItalics: Randy RandyfaceUnderline: Randy Randyface
  • 79. Behavioral DesignPatterns
  • 80. Behavioral DesignPatternsHandle communication between objectsExample PatternsInterpreterIteratorObserver
  • 81. Interpreter Pattern
  • 82. Interpreter PatternAllows you to define a custom languageParses requests based on that languageAssigns appropriate action to handle therequest
  • 83. How’s it work?A class acts as an interpreterThey know the languageThe know how to translate from the givenlanguage to their languageAnother class asks the interpreter to translateThe interpreter translates and returns thetranslation
  • 84. Why would I use this?Provides standardized communicationbetween components, no matter what thelanguageStandardizes a communication method
  • 85. Problem:You are writing an application, and you wouldlike your administrator to customize the emailsthat are sent to a list of users
  • 86. Solution: Interpreter<?phpclass Person{public $name;public $email;public function __construct($name, $email){$this->name = $name;$this->email = $email;}}class MessageInterpreter{public function interpret($message, $person){$data = array(‘name’,’email’);foreach ($data as $d) {$message = str_replace(“[[$d]]”,$person->$d,$message);}return $message;}}<?php$message = “Dear [[name]], “ .“Your email address is [[email]].<br />”;$people = array(new Person(‘joe’, ‘’),new Person(‘sarah’, ‘’),new Person(‘pat’, ‘’));$i = new MessageInterpreter();foreach ($people as $p) {echo $i->interpret($message, $p);}?>Dear joe, Your email address is sarah, Your email address is pat, Your email address is
  • 87. Iterator Pattern
  • 88. Iterator PatternAllows a class to traverse the elements ofanother classAllows encapsulation of the internal structureof how iteration occurs.Provides common interface for traversingmultiple types of collections
  • 89. Practical IteratorsDatabase query resultsFile contentsFiles in a directory
  • 90. Iterator with PHP5PHP5 provides an Iterator interface<?phpinterface Iterator{// Returns the current valuefunction current();// Returns the current keyfunction key();// Moves the internal pointer to the next elementfunction next();// Moves the internal pointer to the first elementfunction rewind();// If the current element is not at all valid (boolean)function valid();}
  • 91. IteratorAggregatePHP5 also provides an IteratorAggregateInterface requiring a getIterator() function
  • 92. Problem:You are writing an application in which youhave a group of people, all managed within acentral object. You want to get the individualpeople from the group so you can print theirinformation.
  • 93. Solution: Iterator<?phpclass Person{protected $_name;protected $_email;public function __construct($name, $email){$this->_name = $name;$this->_email = $email;}public function getName(){return $this->_name;}public function getEmail(){return $this->_email;}}<?phpclass MyIterator implements Iterator{protected $_data;public function __construct(Array $data){$this->_data = $data;}public function rewind(){reset($this->_data);}public function current(){return current($this->_data);}public function key(){return key($this->_data);}public function next(){return next($this->_data);}public function valid(){return ($this->current() !== false);}}
  • 94. Solution: Iterator<?phpclass PersonCollection implements IteratorAggregate{protected $_people = array();public function getIterator() {return new MyIterator($this->_people);}public function add(Person $person){$this->_people[] = $person;}}$people = new PersonCollection();$people->add(new Person(‘joe’, ‘’));$people->add(new Person(‘sarah’, ‘’));$people->add(new Person(‘pat’, ‘’));foreach ($people as $p) {echo $p->getName() . ‘ ‘ . $p->getEmail() . ‘<br />’;}?>joe joe@home.netsarah sarah@aol.compat
  • 95. Observer Pattern
  • 96. Observer PatternAllows one object to notify another when itchanges stateAllows you to avoid tight coupling betweenobjects2 partsListeners (or Observers)Subject
  • 97. How’s it work?Listeners all implement the same interfaceA subject allows listeners to be registeredWhenever an event happens in the subject, theregistered listeners are notified via the methodset in the interfaceThe subject has no idea (nor does it care) whatthe listener does with the information
  • 98. Why would I use this?Extend standard functionality of yourapplicationDe-couple modules in the application
  • 99. Problem:An application you are writing needs to sendemail whenever a new user is added to thesystem
  • 100. Observer Example<?phpinterface PersonObserver{public function notify(Person $person);}class EmailObserver implements PersonObserver{public function notify(Person $person){echo “Sending message to “ .$person->getName() .“ at “ .$person->getEmail() .“.<br />”;// send mail}}<?phpinterface PersonObservable{public function addObserver(PersonObserver $o);}class PersonCollection implements PersonObservable{protected $_observers = array();protected $_people = array();public function addObserver(PersonObserver $o){$this->_observers[] = $o;}public function add(Person $person){$this->_people[] = $person;foreach ($this->_observers as $o) {$o->notify($person);}}}
  • 101. Observer Example<?phpclass Person{protected $_name;protected $_email;public function __construct($name, $email){$this->_name = $name;$this->_email = $email;}public function getName(){return $this->_name;}public function getEmail(){return $this->_email;}}<?php$people = new PersonCollection();$people->addObserver(new EmailObserver());$people->add(new Person(‘joe’, ‘’));$people->add(new Person(‘sarah’, ‘’));$people->add(new Person(‘pat’, ‘’));?>Sending message to joe at message to sarah at message to pat at
  • 102. Quiz time!
  • 103. Quiz Question 1What are the three design pattern categories?• Creational• Structural• Behavioral
  • 104. Quiz Question 2What three things should you do beforeimplementing a design pattern solution?• Understand the problem• Understand the design pattern• Understand how the design pattern solves my problem
  • 105. Quiz Question 3Which creational pattern would be appropriatefor the following scenario:You are writing an application that will connect to adatabase. You need to have a database connectionopen to talk to the database.Singleton!
  • 106. Quiz Question 4Which structural pattern would be appropriatefor the following scenario:You are writing an application for a family tree. Eachmember of each generation should be displayed, andlink any children to them.Composite!
  • 107. Quiz Question 5Which behavioral pattern would be appropriatefor the following scenarioYou are writing a blog and you want to update an RSSfeed every time you add a new post.Observer
  • 108. Quiz Question 6True or False: The decorator pattern is acreational design pattern.False - Decorator is structural
  • 109. Quiz Question 7True or False: You can use multiple differentdesign patterns at a time.True!
  • 110. Quiz Question 8Which of the following is NOT a songperformed by Vanilla Ice?Ninja RapHavin’ A RoniThe Duece is LooseRosta Man
  • 111. Quiz Question 8Which of the following is NOT a songperformed by Vanilla Ice?Ninja RapHavin’ A RoniThe Duece is LooseRosta Man
  • 112. Questions?
  • 113. ArchitecturalPatterns
  • 114. What are Architectural patterns?Patterns which help with overall applicationdesign.Help define...... how the application is structured... how the pieces of the applicationcommunicate with each otherTargeted to solve different types of problems
  • 115. Architectural v/s DesignArchitectural patterns target the entireapplicationDesign patterns target functionality within theapplicationThey are NOT mutually exclusive
  • 116. Why would I use these?Proven foundation on which to developCode readability and portabilitySpeed up development process
  • 117. Types of Architectural PatternsModel-View-Controller (MVC)Service Oriented Architecture (SOA)more...
  • 118. Model-View-Controller
  • 119. Model-View-ControllerMVCBusiness logic is separated from user interface
  • 120. MVC: ModelsModels contain your dataDatabaseWeb ServiceXML DocumentGives meaning to that data
  • 121. MVC: ViewsViews provide the user interface for yourapplicationIn our case, this is the HTML
  • 122. MVC: ControllersAct as a middle manTakes input from the views which invokechanges in the models
  • 123. How’s it work?A user interacts with the view (clicks a button)Controller gets input from the eventController notifies the model of an eventThe model might change state based on the eventThe controller tells the view what the model changedRinse, repeat...
  • 124. Why would I use this?De-couples user interface from the business logicEasily change the user interface without modifyingthe business logicEasily change the business logic without modifyingthe user interfaceAllows graphic designers to design while programmersprogram
  • 125. This seems complicated...It begin withExisting frameworks help a lotZend FrameworkCakePHPComplete OO solutionTake our MVC With Zend Framework class
  • 126. Service-OrientedArchitecture
  • 127. Service-Oriented ArchitectureSOAAllows different applications to exchange data,regardless of their platformWeb services are great examplesSOAPXML-RPC
  • 128. SOA: Building Blocks3 rolesService ProviderService BrokerService Requester
  • 129. SOA: Service ProviderCreates a web serviceCan publish its interface and provides accessinformation to the Service BrokerDetermines which services to expose
  • 130. SOA: Service BrokerAKA Service RegistryResponsible for making the service available toany Service RequesterConnects the Requester to the Provider
  • 131. SOA: Service RequesterRequests the desired web service from theBrokerCalls services from the Provider onceconnected
  • 132. How’s it work?A Provider decides to expose some of its components asa web serviceThe Provider registers with the BrokerA Requester requests the service from the BrokerThe Broker connects the Requester to the ProviderThe Requester uses the service provided by the Provider
  • 133. Why would I use this?Expose part of your application to anotherapplicationAPI - Application Programming InterfaceAllow one application to use data from anotherwithout having intimate knowledge of its datastructure
  • 134. Examples of SOAFlickrGoogle’s GDataAkismetYahooAmazonTechnorati
  • 135. How do I make my own?Frameworks helpPHP5 has some built-in helpersSOAPXML-RPC
  • 136. Quiz time!
  • 137. Quiz Question 9True or False: Architecture patterns are justcollections of multiple design patterns.False
  • 138. Quiz Question 10What are the advantages of using anArchitectural Pattern?Proven foundation on which to developCode readability and portabilitySpeed up development process
  • 139. Quiz Question 11What does SOA stand for?Service Oriented Architecture
  • 140. Quiz Question 12Using an architectural pattern like MVC meansthat I can not use any other design patterns.False
  • 141. Quiz Question 13Who was the original host of $10,000 pyramid?Dick Clark
  • 142. Last chance...
  • 143. Evaluations!Please fill out the evaluations for thisworkshop at on “My Appointments” and find thisworkshop.Click “Evaluate”
  • 144. SourcesGoF Bookhttp://www.wikipedia.orghttp://www.patternsforphp.comhttp://www.phppatterns.com
  • 145. The End!
  • 146. Jason AustinSenior SolutionsImplementation Engineerjason_austin@ncsu.eduGarrison LockeLead DynamicFunctionality