Design Patterns In Action: The Bridge

The Bridge Pattern

The Bridge pattern is a design pattern used to separate the abstraction and implementation of an object. The pattern involves creating two separate classes, an abstraction class and an implementation class, which are then connected by a bridge. The abstraction class defines the interface and the implementation class provides the implementation details.

You’re a hacker, trying to infiltrate the Matrix. You have a trusty computer and a bag of tricks to help you along the way. But what if you wanted to switch to infiltrating a cyberpunk city’s infrastructure? You’d have to change your whole approach, right?

Wrong! With the Bridge pattern, you can separate your hacking methods from the specific target you’re trying to infiltrate. Think of it like having a universal tool kit for all your hacking needs. The abstraction defines the interface, and the implementation provides the details. So whether you’re in the Matrix or taking control of a city’s traffic lights, you’re covered.

In this article, we’re going to take a look at how the Bridge pattern can be implemented in PHP using a cyberpunk theme. We’ll show you how to create separate classes for the abstraction and implementation and how to connect them using a bridge. You’ll see how this pattern allows you to change the implementation without affecting the abstraction, and how it can help you write more flexible and maintainable code.

So grab a cup of cyberpunk coffee, sit back, and get ready for some code hacking action!

interface CyberpunkBridge {
    public function hack();
    public function uploadVirus();
}

class CyberpunkMatrixBridge implements CyberpunkBridge {
    public function hack() {
        echo "Hacking into the Matrix...\n";
    }
    public function uploadVirus() {
        echo "Uploading virus...\n";
    }
}

class CyberpunkCityBridge implements CyberpunkBridge {
    public function hack() {
        echo "Hacking into the city's infrastructure...\n";
    }
    public function uploadVirus() {
        echo "Uploading virus to take control of all the traffic lights...\n";
    }
}

class Hacker {
    protected $bridge;
    public function __construct(CyberpunkBridge $bridge) {
        $this->bridge = $bridge;
    }
    public function doCyberpunkStuff() {
        $this->bridge->hack();
        echo "Hacker: 'I'm in!'\n";
    }
}

class VirusUploader {
    protected $bridge;
    public function __construct(CyberpunkBridge $bridge) {
        $this->bridge = $bridge;
    }
    public function doCyberpunkStuff() {
        $this->bridge->uploadVirus();
        echo "VirusUploader: 'Virus uploaded! System compromised!'\n";
    }
}

$matrixHacker = new Hacker(new CyberpunkMatrixBridge());
$matrixHacker->doCyberpunkStuff();

$cityVirusUploader = new VirusUploader(new CyberpunkCityBridge());
$cityVirusUploader->doCyberpunkStuff();

And for the fans of SOLID:

interface CyberpunkBridge {
    public function hack();
    public function uploadVirus();
}

class CyberpunkMatrixBridge implements CyberpunkBridge {
    public function hack() {
        echo "Hacking into the Matrix...\n";
    }
    public function uploadVirus() {
        echo "Uploading virus...\n";
    }
}

class CyberpunkCityBridge implements CyberpunkBridge {
    public function hack() {
        echo "Hacking into the city's infrastructure...\n";
    }
    public function uploadVirus() {
        echo "Uploading virus to take control of all the traffic lights...\n";
    }
}

interface Cyberpunk {
    public function doCyberpunkStuff();
}

class Hacker implements Cyberpunk {
    protected $bridge;
    public function __construct(CyberpunkBridge $bridge) {
        $this->bridge = $bridge;
    }
    public function doCyberpunkStuff() {
        $this->bridge->hack();
        echo "Hacker: 'I'm in!'\n";
    }
}

class VirusUploader implements Cyberpunk {
    protected $bridge;
    public function __construct(CyberpunkBridge $bridge) {
        $this->bridge = $bridge;
    }
    public function doCyberpunkStuff() {
        $this->bridge->uploadVirus();
        echo "VirusUploader: 'Virus uploaded! System compromised!'\n";
    }
}

$matrixHacker = new Hacker(new CyberpunkMatrixBridge());
$matrixHacker->doCyberpunkStuff();

$cityVirusUploader = new VirusUploader(new CyberpunkCityBridge());
$cityVirusUploader->doCyberpunkStuff();
  1. Single Responsibility Principle (SRP): Each class has a single responsibility and is only responsible for one specific task. The CyberpunkMatrixBridge and CyberpunkCityBridge classes are responsible for providing the implementation details for hacking and uploading viruses, respectively. The Hacker and VirusUploader classes are responsible for defining how the action should be performed.
  2. Open-Closed Principle (OCP): The classes are open for extension but closed for modification. The Hacker and VirusUploader classes can be extended to add new functionality without modifying the existing code. Adding a new Cyberpunk implementation will not impact the existing classes and adding a new CyberpunkBridge implementation will not impact the Hacker and VirusUploader classes.
  3. Liskov Substitution Principle (LSP): The derived classes should be substitutable for their base classes. The Hacker and VirusUploader classes are derived from the Cyberpunk interface and are substitutable for it.
  4. Interface Segregation Principle (ISP): The interfaces are small and focused, and they contain only methods that are relevant to the classes that implement them. Cyberpunk interface has only one method and the CyberpunkBridge interface has only two methods.
  5. Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules, but they should depend on abstractions. The Hacker and VirusUploader classes depend on the Cyberpunk interface, and the CyberpunkMatrixBridge and CyberpunkCityBridge classes depend on the CyberpunkBridge interface.
Related Posts