mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-08-04 14:07:25 +02:00
cs Visitor
This commit is contained in:
@@ -39,7 +39,7 @@ class VisitorTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException InvalidArgumentException
|
* @expectedException \InvalidArgumentException
|
||||||
* @expectedExceptionMessage Mock
|
* @expectedExceptionMessage Mock
|
||||||
*/
|
*/
|
||||||
public function testUnknownObject()
|
public function testUnknownObject()
|
||||||
|
@@ -3,11 +3,10 @@
|
|||||||
namespace DesignPatterns\Visitor;
|
namespace DesignPatterns\Visitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An example of a Visitee : Group
|
* An example of a Visitor: Group
|
||||||
*/
|
*/
|
||||||
class Group extends Role
|
class Group extends Role
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
@@ -28,5 +27,4 @@ class Group extends Role
|
|||||||
{
|
{
|
||||||
return "Group: " . $this->name;
|
return "Group: " . $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,34 +7,34 @@ namespace DesignPatterns\Visitor;
|
|||||||
*
|
*
|
||||||
* Purpose:
|
* Purpose:
|
||||||
* The Visitor Pattern lets you outsource operations on objects to other objects. The main reason to do this is to keep
|
* The Visitor Pattern lets you outsource operations on objects to other objects. The main reason to do this is to keep
|
||||||
* a seperation of concerns. But classes have to define an contract to allow visitors (the "accept" method in the example below).
|
* a separation of concerns. But classes have to define an contract to allow visitors (the "accept" method in the example below).
|
||||||
*
|
*
|
||||||
* The contract is an abstract class but you can have also a clean interface.
|
* The contract is an abstract class but you can have also a clean interface.
|
||||||
* In that case, each Visitee has to choose itself which method to invoke on the visitor.
|
* In that case, each Visitor has to choose itself which method to invoke on the visitor.
|
||||||
*/
|
*/
|
||||||
abstract class Role
|
abstract class Role
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method handles a double dispatch based on the shortname of the Visitee
|
* This method handles a double dispatch based on the short name of the Visitor
|
||||||
*
|
*
|
||||||
* Feel free to override it if your object must call another visiting behavior
|
* Feel free to override it if your object must call another visiting behavior
|
||||||
*
|
*
|
||||||
* @param \DesignPatterns\Visitor\RoleVisitor $visitor
|
* @param \DesignPatterns\Visitor\RoleVisitorInterface $visitor
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
public function accept(RoleVisitor $visitor)
|
public function accept(RoleVisitorInterface $visitor)
|
||||||
{
|
{
|
||||||
// this trick to simulate double-dispatch based on type-hinting
|
// this trick to simulate double-dispatch based on type-hinting
|
||||||
$fqcn = get_called_class();
|
$klass = get_called_class();
|
||||||
preg_match('#([^\\\\]+)$#', $fqcn, $extract);
|
preg_match('#([^\\\\]+)$#', $klass, $extract);
|
||||||
$visitingMethod = 'visit' . $extract[1];
|
$visitingMethod = 'visit' . $extract[1];
|
||||||
|
|
||||||
// this ensures strong typing with visitor interface, not some visitor objects
|
// this ensures strong typing with visitor interface, not some visitor objects
|
||||||
if (!method_exists(__NAMESPACE__ . '\RoleVisitor', $visitingMethod)) {
|
if (!method_exists(__NAMESPACE__ . '\RoleVisitorInterface', $visitingMethod)) {
|
||||||
throw new \InvalidArgumentException("The visitor you provide cannot visit a $fqcn instance");
|
throw new \InvalidArgumentException("The visitor you provide cannot visit a $klass instance");
|
||||||
}
|
}
|
||||||
|
|
||||||
call_user_func(array($visitor, $visitingMethod), $this);
|
call_user_func(array($visitor, $visitingMethod), $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,11 +7,10 @@ namespace DesignPatterns\Visitor;
|
|||||||
*
|
*
|
||||||
* An implementation of a concrete Visitor
|
* An implementation of a concrete Visitor
|
||||||
*/
|
*/
|
||||||
class RolePrintVisitor implements RoleVisitor
|
class RolePrintVisitor implements RoleVisitorInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function visitGroup(Group $role)
|
public function visitGroup(Group $role)
|
||||||
{
|
{
|
||||||
@@ -19,11 +18,10 @@ class RolePrintVisitor implements RoleVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function visitUser(User $role)
|
public function visitUser(User $role)
|
||||||
{
|
{
|
||||||
echo "Role: " . $role->getName();
|
echo "Role: " . $role->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -13,9 +13,8 @@ namespace DesignPatterns\Visitor;
|
|||||||
* Note 2 : the visitor must not choose itself which method to
|
* Note 2 : the visitor must not choose itself which method to
|
||||||
* invoke, it is the Visitee that make this decision.
|
* invoke, it is the Visitee that make this decision.
|
||||||
*/
|
*/
|
||||||
interface RoleVisitor
|
interface RoleVisitorInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a User object
|
* Visit a User object
|
||||||
*
|
*
|
||||||
@@ -24,7 +23,7 @@ interface RoleVisitor
|
|||||||
public function visitUser(User $role);
|
public function visitUser(User $role);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a Group objet
|
* Visit a Group object
|
||||||
*
|
*
|
||||||
* @param \DesignPatterns\Visitor\Group $role
|
* @param \DesignPatterns\Visitor\Group $role
|
||||||
*/
|
*/
|
@@ -9,7 +9,6 @@ namespace DesignPatterns\Visitor;
|
|||||||
*/
|
*/
|
||||||
class User extends Role
|
class User extends Role
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
@@ -30,6 +29,4 @@ class User extends Role
|
|||||||
{
|
{
|
||||||
return "User " . $this->name;
|
return "User " . $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user