Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<blockquote> <p>So, in the <code>__construct</code> of the Person class, I'd like it to check for the users sex and set the appropriate sub-class.</p> </blockquote> <p>Like already said elsewhere, ctors do not return, so you cannot do that. And ctors should not query the database anyway, because <a href="http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/" rel="nofollow">that would be doing work</a>. If you cannot/want not create the correct subtype immediately via <a href="http://martinfowler.com/eaaCatalog/dataMapper.html" rel="nofollow">DataMapper</a> or <a href="http://martinfowler.com/eaaCatalog/repository.html" rel="nofollow">Repository</a>, you can use a <a href="http://sourcemaking.com/design_patterns/state" rel="nofollow">State Pattern</a>:</p> <blockquote> <p>Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.</p> </blockquote> <p>This is one of the <a href="http://sourcemaking.com/behavioral_patterns" rel="nofollow">Behavioral Patterns</a> from the <a href="https://en.wikipedia.org/wiki/Design_Patterns" rel="nofollow">Gang Of Four book</a>. The keyword, obviously, is behavior here. The State pattern is not about varying Subtypes (Cat, Dog) as such, but rather about the difference in the behavior those have. Hence my comments to your question.</p> <h3>Example:</h3> <pre><code>interface GenderBehavior { public function someBehavior(); // can add more methods here } class FemalePersonBehavior implements GenderBehavior { public function someBehavior() { // female specific behavior } } class MalePersonBehavior implements GenderBehavior { public function someBehavior() { // male specific behavior } } class UnknownGenderBehavior implements GenderBehavior { public function someBehavior() { // either implement a neutral behavior or throw new LogicException('Unknown Gender set'); } } </code></pre> <p>To create those instances, you add a <a href="http://sourcemaking.com/design_patterns/abstract_factory" rel="nofollow">Factory</a></p> <pre><code>class GenderBehaviorFactory { public static function create($sex = null) { switch ($sex) { case 'male': return new MalePersonBehavior; case 'female': return new FemalePersonBehavior; default: return UnknownGenderBehavior; } } } </code></pre> <p>Then you add the <code>GenderBehavior</code> interface to the <code>Person</code> class and tunnel all access to the interface methods to the Behavior instance:</p> <pre><code>class Person implements GenderBehavior { private $behavior; public function __construct() { $this-&gt;behavior = GenderBehaviorFactory::create(); } public function changeGender($sex) { $this-&gt;behavior = GenderBehaviorFactory::create($sex); } public function someBehavior() { $this-&gt;behavior-&gt;someBehavior(); } } </code></pre> <p>Now when you create a Person the first time, it will instantiate with an <code>UnknownGenderBehavior</code> and if you try to call <code>someBehavior</code>, it will raise an Exception. When you call <code>changeGender</code> with either male or female as argument, the appropriate <code>GenderBehavior</code> will be created and set to <code>Person</code>. And then you can call <code>someBehavior</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload