diff --git a/TemplateMethod/BeachJourney.php b/TemplateMethod/BeachJourney.php new file mode 100644 index 0000000..cec7bab --- /dev/null +++ b/TemplateMethod/BeachJourney.php @@ -0,0 +1,20 @@ +buyAFlight(); + $this->takePlane(); + $this->enjoyVacation(); + $this->buyGift(); + $this->takePlane(); + } + + /** + * This method must be implemented, this is the key-feature of this pattern + */ + abstract protected function enjoyVacation(); + + /** + * This method is also part of the algorithm but it is optional. + * This is an "adapter" (do not confuse with the Adapter pattern, not related) + * You can override it only if you need to. + */ + protected function buyGift() + { + + } + + // this method will be unknown by subclasses (better) + private function buyAFlight() + { + echo "Buying a flight\n"; + } + + // sbclasses will get access to this method but cannot override it and + // compromise this algorithm (warning : cause of cyclic depedencies) + final protected function takePlane() + { + echo "Taking the plane\n"; + } + + // A note regarding the keyword "final" : don't use it when you start coding : + // add it after you narrow and know exacly what change and what remain unchanged + // in this algorithm. + // [abstract] x [3 access] x [final] = 12 combinations, it can be hard ! +} \ No newline at end of file diff --git a/Tests/TemplateMethod/JourneyTest.php b/Tests/TemplateMethod/JourneyTest.php new file mode 100644 index 0000000..fcfc4e6 --- /dev/null +++ b/Tests/TemplateMethod/JourneyTest.php @@ -0,0 +1,49 @@ +expectOutputRegex('#sun-bathing#'); + $journey->takeATrip(); + } + + public function testCity() + { + $journey = new TemplateMethod\CityJouney(); + $this->expectOutputRegex('#drink#'); + $journey->takeATrip(); + } + + /** + * How to test an abstract template method with PHPUnit + */ + public function testLasVegas() + { + $journey = $this->getMockForAbstractClass('DesignPatterns\TemplateMethod\Journey'); + $journey->expects($this->once()) + ->method('enjoyVacation') + ->will($this->returnCallback(array($this, 'mockUpVacation'))); + $this->expectOutputRegex('#Las Vegas#'); + $journey->takeATrip(); + } + + public function mockUpVacation() + { + echo "Fear and loathing in Las Vegas\n"; + } + +} \ No newline at end of file