State/Strategy pattern – visibility problem
I am implementing the state pattern in one of my projects and is running into a design issue; my problem can be abstractly described as follows:
Let's say I have the StatefulObject Class that has a state property which holds the CurrentState object.
Much of the functionally I'd like the CurrentState object to access, is encapsulated in the StatefulObject object.
The problem is that allowing access to this functionality forces me to provide public methods in the StatefulObject class that I would otherwise have not exposed, and also feel I shouldn't.
I'd welcome suggestions on how to handle this visibility issue.
The implementation language is PHP, if that maters.
I've put together some example code, according to request:
Class StatefulObject{
protected $state;
public function StatefulObject(){
$this->state = new PrepareSate($this);
}
public function execute(){
$this->state->execute();
}
/* I am not intrested in providing public access to these methods
Optimaly I would have this visible only for the PrepareState*/
public function setX(){
};
public function setY(){
};
}
Abstract class StateObject{
protected $stateFulObjectRef;
public function StateObject(StateFulObject $ref){
$this->stateFulObjectRef = $ref;
}
}
Class PrepareState extends StateObject{
public function execute(){
/* This is why I need the public access for */
$this->stateFulObjectRef->setX();
$this->stateFulObjectRef->setY();
}
}
I think th开发者_如何转开发at the solution in Java would be having the methods setX setY with no access modifier, which means they will be visible at package level.
I don't think PHP has an equivalent solution though.
EDIT, on to possible answer:
I think the best solution I came up with so far is making StatefulObject and the StateObject inherit the same father (solely for visibility). and the declare the setX setY methods as protected. Sibling classes has access to each other protected methods in PHP - as pointed out here - http://www.php.net/manual/en/language.oop5.visibility.php#93743
The question is very general but I will try to answer based on my understanding of your problem (which could be not a correct understanding of the problem)
I will suggest that you make an interface and implement it in your class and than use that interface object to interact with the methods.
If your StateObject does not need access to the StatefulObject at all, then just simply pass the needed values in parameters(Strategy pattern).
Class StatefulObject{
protected $state;
public function StatefulObject(){
$this->state = new PrepareSate($this);
}
public function execute(){
$this->state->execute($this->x, $this->y);
}
}
Class PrepareState extends StateObject{
public function execute($x, $y){
// Now you have access to $x and $y.
}
}
精彩评论