Abstract Server

Overview

The Abstract Server is one of the simplest patterns to implement and understand. I wouldn’t be surprised if you already are using this pattern in your daily developing.

The Problem

I find it best to communicate through code rather than through words so I will provide a test case to help explain the use case.

function testSwitchControlsLight() {
    $light = new Light();
    $switch = new Switch($light);
    $switch->press();
    $this->assertTrue($light->isOn());
}

So we have a Switch that requires a Light. When the Switch is pressed it will turn the Light on. And here is the code for the two classes:

class Switch {
    protected $light;

    public function __construct(Light $light) {
        $this->light = $light;
    }

    public function press() {
        if ($this->light->isOn()) {
            $this->light->turnOff();
        } else {
            $this->light->turnOn();
        }
    }
}

class Light {
    protected $isOn = false;

    public function turnOn() {
        $this->isOn = true;
    }

    public function turnOff() {
        $this->isOn = false;
    }

    public function isOn() {
        return $this->isOn;
    }
}

This is a simple program with a simple flaw. The Switch class depends on the Light class. That means that if the Light class ever changes then the Switch class may also have to change making the code more complicated and harder to maintain. It also means that you can’t reuse the Switch to control something else like a Fan.

This is an example of breaking the dependency-inversion principle for SOLID object-oriented design. This principle states that classes should depend on abstractions and not concretions. It also breaks the Open-Closed Principle because the Switch can’t be reused without editing the code.

The Solution

Instead of Switch depending on the Light class it should implement the Abstract Server pattern and depend on an abstract class that has abstract methods for the functionality Switch needs.

Before UML diagram of the Switch class depending on the Light class
Abstract Server Before

After UML diagram of the Switchable interface
Abstract Server After

As we can see from this diagram the Switch depends on a generic Switchable interface so that any time we want to add any new devices we don’t have to change the code for Switch. Here is the updated code:

class Switch {
    protected $switchable;

    public function __construct(Switchable $switchable) {
        $this->switchable = $switchable;
    }

    public function press() {
        if ($this->switchable->isOn()) {
            $this->switchable->turnOff();
        } else {
            $this->switchable->turnOn();
        }
    }
}

abstract class Switchable {
    abstract public function turnOn();
    abstract public function turnOff();
    abstract public function isOn();
}

class Light extends Switchable {
    protected $isOn = false;

    public function turnOn() {
        $this->isOn = true;
    }

    public function turnOff() {
        $this->isOn = false;
    }

    public function isOn() {
        return $this->isOn;
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

About the Author

  • Chris LondonSenior Web ArchitectPartners In Leadership

    I've always worked as an innovative programmer. My insights and creative thinking result in superior products and customer satisfaction. Working full time as a senior web architect I've used lots of exciting technologies (i.e., Ember, Backbone, Handlebars, etc) and developed a lot of exciting sites. In my spare time I hope to develop even more exciting and new technologies. I've been programming professionally for 9 years in everything from desktop applications to web applications to mobile applications.

    Web: https://plus.google.com/116403409191372324375