I've seen/used some objects that have a structure like so, designed to let children extend the functionality of functions without having to override them. Is there a name for this pattern?
code example:
class CrudModel {
public function create($data) {
$data = $this->pre_create($data);
//create logic
}
public function delete($data) {
$data = $this->pre_delete($data);
//delete logic
}
protected function pre_create($data) { //empty }
protected function pre_delete($data) { //empty }
}
class SpecificCrudModel extends Model {
protected function pre_create($data) {
//custom logic for this object.
}
}
-
I wish I could see a longer, more concrete example. Btw, what language is this?Job– Job09/01/2011 15:01:50Commented Sep 1, 2011 at 15:01
-
1@Job: if I had to guess, PHP.Brad Christie– Brad Christie09/01/2011 15:06:52Commented Sep 1, 2011 at 15:06
2 Answers 2
It looks like a template method pattern, but the methods in question are not abstract and the child class is not being forced to implement them. I'd say it's just a common use of inheritance or maybe a borderline template method pattern.
I'd rather implement such things via events/delegates/callbacks, though. It is much clearer then what you can hook up to and you can't accidentally override necessary behaviour. It's also more flexible.
@GSto
Here's an example of using callbacks with PHP. It's not as elegant as in other languages with native event support (like C# offers for example), but it's flexible and you can register such callbacks in the constructor of a child class for example. This website here told me how to implement callbacks in PHP, the heart of it is the call_user_func function of PHP. This can register as many handlers as you like and anything with a reference to the object can register handlers.
class Model {
protected $_before_create_callbacks = array();
protected $_after_create_callbacks = array();
function register_before_create_handler($callback) {
$this->_before_create_callbacks[] = $callback;
}
function register_after_create_handler($callback) {
$this->_after_create_callbacks[] = $callback;
}
function create(){
$this->before_create();
//logic of create...
$this->after_create();
}
protected function before_create() {
foreach ($this->_before_create_callbacks as $callback){
call_user_func($callback);
}
}
protected function before_create() {
foreach ($this->$_after_create_callbacks as $callback){
call_user_func($callback);
}
}
}
function someFunction(){
logSomething();
}
$anyModel->register_before_create_handler("someFunction");
-
interesting, do you have an example of how you would handle this in the manner you described?GSto– GSto09/01/2011 15:19:39Commented Sep 1, 2011 at 15:19
-
2AFAIK this is template method pattern (or a variation of it), and when the Wikipedia article talks about "abstract methods", IMHO it does not mean necessarily methods which force the subclass to implement them, but also virtual methods which may have an empty (or even a non-empty) default implementation.Doc Brown– Doc Brown09/01/2011 15:38:38Commented Sep 1, 2011 at 15:38
-
@Doc Brown: You can call it a variation. I think it's just close enough to call it template method, but it isn't a classical template method pattern and thus it becomes classical method overriding, basically just usage of inheritance. Also, see wikipedia's definition of abstract method, they do mean it in an OOP sense.Falcon– Falcon09/01/2011 15:57:13Commented Sep 1, 2011 at 15:57
-
@GSto: Give me some time, I'm gonna write an example, probably tomorrow.Falcon– Falcon09/01/2011 16:15:17Commented Sep 1, 2011 at 16:15
-
1@Falcon: well, I have the GOF book here in my hand and the description of the template method pattern does not insist the virtual methods have to be pure virtual / abstract. In fact, hooks with empty default implementation are explicitly mentioned. I gave you +1, either.Doc Brown– Doc Brown09/01/2011 16:26:08Commented Sep 1, 2011 at 16:26
This looks like a pretty standard case of any inheritance-based model, depending on how you use it. It's pretty common to put any implementation specific code in virtual functions in an abstract parent, and to implement them in a child class.
This is literally the exemplar case in c++; it looks like you're using PHP, here, and this is definitely the preferred method. Much easier to follow than using callbacks. If you're using this in an MVC framework (Or building one) you might want to prepend a '_' to the setup utility call.