Showing posts with label Bridge Pattern. Show all posts
Showing posts with label Bridge Pattern. Show all posts

Sunday, 26 January 2014

Bridge Design pattern - Implementation [LED TV]

Master Software Architecture & Clean Code!

Subscribe to Ram N Java for clean code, design pattern implementations, and practical Java tutorials!

SUBSCRIBE NOW

What is the Bridge Design Pattern?

The Bridge Design Pattern is a structural pattern whose main goal is to decouple an abstraction from its implementation so that both can vary independently. Instead of relying heavily on inheritance—which often leads to an explosion of subclasses—the Bridge pattern prefers object composition.

In this LED TV example, the user control interface (like a remote control) acts as the abstraction, while the actual TV hardware (Sony, Samsung, LG) acts as the implementation.

Complete Java Code Implementation

Below is a clean, practical implementation illustrating the Bridge pattern using an LED TV and remote control hierarchy:

// 1. Implementor Interface
interface LedTv {
    void on();
    void off();
    void switchChannel(int channel);
}

// 2. Concrete Implementors
class SonyLedTv implements LedTv {
    @Override
    public void on() {
        System.out.println("Sony TV is turned ON.");
    }
    @Override
    public void off() {
        System.out.println("Sony TV is turned OFF.");
    }
    @Override
    public void switchChannel(int channel) {
        System.out.println("Sony TV tuned to channel: " + channel);
    }
}

class SamsungLedTv implements LedTv {
    @Override
    public void on() {
        System.out.println("Samsung TV is turned ON.");
    }
    @Override
    public void off() {
        System.out.println("Samsung TV is turned OFF.");
    }
    @Override
    public void switchChannel(int channel) {
        System.out.println("Samsung TV tuned to channel: " + channel);
    }
}

// 3. Abstraction (Bridge container)
abstract class RemoteControl {
    protected LedTv tv;

    public RemoteControl(LedTv tv) {
        this.tv = tv;
    }

    public abstract void turnOn();
    public abstract void turnOff();
    public abstract void setChannel(int channel);
}

// 4. Refined Abstraction
class BasicRemoteControl extends RemoteControl {
    public BasicRemoteControl(LedTv tv) {
        super(tv);
    }

    @Override
    public void turnOn() {
        tv.on();
    }

    @Override
    public void turnOff() {
        tv.off();
    }

    @Override
    public void setChannel(int channel) {
        tv.switchChannel(channel);
    }
}

// 5. Client Application
public class BridgePatternDemo {
    public static void main(String[] args) {
        // Control Sony TV
        LedTv sonyTv = new SonyLedTv();
        RemoteControl sonyRemote = new BasicRemoteControl(sonyTv);
        sonyRemote.turnOn();
        sonyRemote.setChannel(5);
        sonyRemote.turnOff();

        System.out.println("--------------------");

        // Control Samsung TV using the same abstraction
        LedTv samsungTv = new SamsungLedTv();
        RemoteControl samsungRemote = new BasicRemoteControl(samsungTv);
        samsungRemote.turnOn();
        samsungRemote.setChannel(12);
        samsungRemote.turnOff();
    }
}

Key Architectural Advantages

  • Decoupled Hierarchies: Both abstraction (Remotes) and implementation (TV brands) can grow independently without cross-affecting code.
  • Eliminates Class Explosion: Avoids creating permutations like SonyBasicRemote, SamsungBasicRemote, SonySmartRemote, etc.
  • Runtime Flexibility: Concrete implementations can be swapped easily at runtime through constructor or setter injection.

Watch More Related Design Pattern Tutorials


Click here to watch in Youtube : https://www.youtube.com/watch?v=iCSrIzVSZwM

Click the below Image to Enlarge

Bridge Design pattern - Implementation [LED TV]



















Bridge Design pattern - Implementation [LED TV] - Class Diagram




























LEDTV.java

public interface LEDTV
{
public void switchOn();

public void switchOff();

public void setChannel(int channelNumber);
}


SamsungLedTv.java

public class SamsungLedTv implements LEDTV
{

@Override
public void switchOn()
{
System.out.println("Turning ON.. Samsung TV.");
}

@Override
public void switchOff()
{
System.out.println("Turning Off.. Samsung TV.");

}

@Override
public void setChannel( int channelNumber )
{
System.out.println("Setting channel Number " + channelNumber + ".. on Samsung TV");

}

}


SonyLedTv.java

public class SonyLedTv implements LEDTV
{

@Override
public void switchOn()
{
System.out.println("Turning ON.. Sony TV.");
}

@Override
public void switchOff()
{
System.out.println("Turning Off.. Sony TV.");

}

@Override
public void setChannel( int channelNumber )
{
System.out.println("Setting channel Number " + channelNumber + ".. on Sony TV");

}

}


AbstractRemoteControl.java

abstract class AbstractRemoteControl
{

protected LEDTV ledTv;

protected AbstractRemoteControl( LEDTV ledTv )
{
this.ledTv = ledTv;
}

public abstract void switchOn();

public abstract void switchOff();

public abstract void setChannel( int channelNumber );

}

SamsungRemoteControl.java

public class SamsungRemoteControl extends AbstractRemoteControl
{

public SamsungRemoteControl( LEDTV ledtv )
{
super(ledtv);
}

@Override
public void switchOn()
{
ledTv.switchOn();
}

@Override
public void switchOff()
{
ledTv.switchOff();

}

@Override
public void setChannel( int channelNumber )
{
ledTv.setChannel(channelNumber);
}

}

SonyRemoteControl.java

public class SonyRemoteControl extends AbstractRemoteControl
{
public SonyRemoteControl( LEDTV ledtv )
{
super(ledtv);
}

@Override
public void switchOn()
{
ledTv.switchOn();
}

@Override
public void switchOff()
{
ledTv.switchOff();

}

@Override
public void setChannel( int channelNumber )
{
ledTv.setChannel(channelNumber);
}
}

Client.java

public class Client
{

public static void main( String[] args )
{

SonyRemoteControl sonyRemoteControl = new SonyRemoteControl(new SonyLedTv());
sonyRemoteControl.switchOn();
sonyRemoteControl.switchOff();
sonyRemoteControl.setChannel(20);
System.out.println("**********************************************************************");
SamsungRemoteControl samsungRemoteControl = new SamsungRemoteControl(new SamsungLedTv());
samsungRemoteControl.switchOn();
samsungRemoteControl.switchOff();
samsungRemoteControl.setChannel(20);
}
}

Output

Turning ON.. Sony TV.
Turning Off.. Sony TV.
Setting channel Number 20.. on Sony TV
**********************************************************************
Turning ON.. Samsung TV.
Turning Off.. Samsung TV.
Setting channel Number 20.. on Samsung TV

See also:

  • Bridge Design pattern - Introduction
  • Bridge Design pattern - Real time example [Send Message]
  • Bridge Design pattern - Real time example [Publish Message]
  • Bridge Design pattern - Real time example [Shape]
  • Bridge Design pattern - Real time example [TV]
  • Bridge Design pattern - Class Diagram
  • Bridge Design pattern - Implementation [Shape]
  • Bridge Design pattern - Implementation [Send Message]
  • Bridge Design pattern - Implementation [Publish Message]
  • Bridge Design pattern - Keypoints
  • All Design Patterns Links
  • Bridge Design pattern - Implementation [Publish Message]

    Master Software Architecture & Clean Code!

    Subscribe to Ram N Java for clean code, design pattern implementations, and practical Java tutorials!

    SUBSCRIBE NOW

    What is the Bridge Design Pattern?

    The Bridge Design Pattern decouples an abstraction from its implementation so that both can evolve independently. Instead of relying on rigid, multi-level class inheritance—which causes an explosion of subclasses—the Bridge pattern connects separate class hierarchies through composition.

    In a message publishing or notification system, the type of message being processed (e.g., text, encrypted, or urgent) acts as the abstraction, while the delivery platform (e.g., Email, SMS, or Push Notification) serves as the concrete implementation.

    Complete Java Code Implementation

    Below is a clean, practical Java implementation illustrating the Bridge pattern with a real-world message publishing architecture:

    // 1. Implementor Interface
    interface MessageSender {
        void sendMessage(String message);
    }
    
    // 2. Concrete Implementors
    class EmailSender implements MessageSender {
        @Override
        public void sendMessage(String message) {
            System.out.println("Email: Sending message -> " + message);
        }
    }
    
    class SmsSender implements MessageSender {
        @Override
        public void sendMessage(String message) {
            System.out.println("SMS: Sending text -> " + message);
        }
    }
    
    // 3. Abstraction (Bridge holding the Implementor reference)
    abstract class Message {
        protected MessageSender messageSender;
    
        public Message(MessageSender messageSender) {
            this.messageSender = messageSender;
        }
    
        public abstract void publish(String content);
    }
    
    // 4. Refined Abstractions
    class TextMessage extends Message {
        public TextMessage(MessageSender messageSender) {
            super(messageSender);
        }
    
        @Override
        public void publish(String content) {
            messageSender.sendMessage("[Standard Text] " + content);
        }
    }
    
    class EncryptedMessage extends Message {
        public EncryptedMessage(MessageSender messageSender) {
            super(messageSender);
        }
    
        @Override
        public void publish(String content) {
            String encryptedContent = new StringBuilder(content).reverse().toString();
            messageSender.sendMessage("[Encrypted] " + encryptedContent);
        }
    }
    
    // 5. Client Application
    public class BridgePatternDemo {
        public static void main(String[] args) {
            // Send a text message via Email
            Message emailMessage = new TextMessage(new EmailSender());
            emailMessage.publish("Welcome to Ram N Java!");
    
            // Send an encrypted message via SMS
            Message smsMessage = new EncryptedMessage(new SmsSender());
            smsMessage.publish("TopSecretCode123");
    
            // Swap channels dynamically: Send encrypted content via Email
            Message secureEmail = new EncryptedMessage(new EmailSender());
            secureEmail.publish("ConfidentialReport2026");
        }
    }

    Key Architectural Advantages

    • Prevents Combinatorial Subclass Explosion: Adding 3 message types and 3 delivery channels creates only 6 classes instead of 9 tightly coupled variants.
    • Runtime Channel Switching: Delivery mechanisms can be injected dynamically at runtime based on configuration or user preferences.
    • Open/Closed Principle: You can add a new messaging format or a new transport channel without modifying existing classes.

    Watch More Related Design Pattern Tutorials


    Click here to watch in Youtube : https://www.youtube.com/watch?v=Q2L3FGnjPu0

    Click the below Image to Enlarge

    Bridge Design pattern - Implementation [Publish Message]

    Bridge Design pattern - Implementation [Publish Message] - Class Diagram


    MessagePublisher.java

    public interface MessagePublisher
    {
    public void publishMessage(String message);
    }


    Facebook.java

    public class Facebook implements MessagePublisher
    {

    public void publishMessage(String message)
    {
    System.out.println("'"+message+ "' : This message has been published to public in Facebook Social networking site");
    }
    }

    Twitter.java

    public class Twitter implements MessagePublisher
    {

    public void publishMessage(String message)
    {
    System.out.println("'"+message+ "' : This message has been published to public in Twitter Social networking site");
    }
    }

    GooglePlus.java

    public class GooglePlus implements MessagePublisher
    {

    public void publishMessage(String message)
    {
    System.out.println("'"+message+ "' : This message has been published to public in GooglePlus Social networking site");
    }
    }


    Message.java

    abstract class Message
    {

    protected MessagePublisher messagePublisher;

    protected MessagePublisher getMessagePublisher()
    {
    return messagePublisher;
    }

    protected void setMessagePublisher( MessagePublisher messagePublisher )
    {
    this.messagePublisher = messagePublisher;
    }

    abstract public void publishMessage(String message);

    }

    LongMessage.java

    public class LongMessage extends Message
    {

    @Override
    public void publishMessage( String message )
    {
    messagePublisher.publishMessage(message);
    }

    }

    ShortMessage.java

    public class ShortMessage extends Message
    {

    private static int MESSAGE_LENGTH = 200;

    @Override
    public void publishMessage( String message )
    {
    if( message.length() <= MESSAGE_LENGTH )
    {
    messagePublisher.publishMessage(message);
    }
    else
    {
    System.out.println("Sorry message length is more cann't publish.....");
    }

    }

    }


    Client.java

    import java.util.Scanner;

    public class Client
    {

    public static void main( String[] args )
    {

    System.out.println("Please enter the Social networking site you want to use to publish the message  : 'Twitter' or 'Facebook' or 'GooglePlus'");
    Scanner scanner = new Scanner(System.in);
    String socialNetworkingSite = scanner.next();
    System.out.println("Please enter the message you want to publish");
    Scanner scanner1 = new Scanner(System.in);
    String message = scanner1.nextLine();

    if( "Twitter".equalsIgnoreCase(socialNetworkingSite) )
    {
    ShortMessage shortMessage = new ShortMessage();
    shortMessage.setMessagePublisher(new Twitter());
    shortMessage.publishMessage(message);
    }
    else if( "Facebook".equalsIgnoreCase(socialNetworkingSite) )
    {
    LongMessage longMessage = new LongMessage();
    longMessage.setMessagePublisher(new Facebook());
    longMessage.publishMessage(message);
    }
    else if( "GooglePlus".equalsIgnoreCase(socialNetworkingSite) )
    {
    LongMessage longMessage = new LongMessage();
    longMessage.setMessagePublisher(new GooglePlus());
    longMessage.publishMessage(message);
    }

    }
    }


    Output

    Please enter the Social networking site you want to use to publish the message  : 'Twitter' or 'Facebook' or 'GooglePlus'
    Twitter
    Please enter the message you want to publish
    hello
    'hello' : This message has been published to public in Twitter Social networking site


    Please enter the Social networking site you want to use to publish the message  : 'Twitter' or 'Facebook' or 'GooglePlus'
    Facebook
    Please enter the message you want to publish
    hello bow are you?
    'hello bow are you?' : This message has been published to public in Facebook Social networking site

    See also:

  • Bridge Design pattern - Introduction
  • Bridge Design pattern - Real time example [Send Message]
  • Bridge Design pattern - Real time example [Publish Message]
  • Bridge Design pattern - Real time example [Shape]
  • Bridge Design pattern - Real time example [TV]
  • Bridge Design pattern - Class Diagram
  • Bridge Design pattern - Implementation [Shape]
  • Bridge Design pattern - Implementation [Send Message]
  • Bridge Design pattern - Implementation [LED TV]
  • Bridge Design pattern - Keypoints
  • All Design Patterns Links
  • Saturday, 25 January 2014

    Bridge Design pattern - Implementation [Send Message]

    Master Software Architecture & Clean Code!

    Subscribe to Ram N Java for clean code, design pattern implementations, and practical Java tutorials!

    SUBSCRIBE NOW

    Decoupling Abstraction and Implementation

    The Bridge Design Pattern separates an abstraction from its underlying implementation, allowing both class hierarchies to vary independently. In real-world enterprise applications, hardcoding messaging channels directly into message types leads to tight coupling and unnecessary subclass proliferation.

    By utilizing object composition instead of deep inheritance, the Bridge pattern provides a clean, maintainable structure where message categories and delivery transports remain loosely coupled.

    Complete Java Code Walkthrough

    Here is an end-to-end implementation illustrating message sending across multiple delivery channels using the Bridge pattern:

    // 1. Implementor Interface
    interface MessageSender {
        void sendMessage(String message);
    }
    
    // 2. Concrete Implementors
    class EmailSender implements MessageSender {
        @Override
        public void sendMessage(String message) {
            System.out.println("Email: Sending -> " + message);
        }
    }
    
    class SmsSender implements MessageSender {
        @Override
        public void sendMessage(String message) {
            System.out.println("SMS: Sending -> " + message);
        }
    }
    
    // 3. Abstraction
    abstract class Message {
        protected MessageSender messageSender;
    
        public Message(MessageSender messageSender) {
            this.messageSender = messageSender;
        }
    
        public abstract void send(String content);
    }
    
    // 4. Refined Abstraction
    class UrgentMessage extends Message {
        public UrgentMessage(MessageSender messageSender) {
            super(messageSender);
        }
    
        @Override
        public void send(String content) {
            messageSender.sendMessage("[URGENT ALERT] " + content);
        }
    }
    
    class NormalMessage extends Message {
        public NormalMessage(MessageSender messageSender) {
            super(messageSender);
        }
    
        @Override
        public void send(String content) {
            messageSender.sendMessage("[INFO] " + content);
        }
    }
    
    // 5. Client Application
    public class MessageBridgeDemo {
        public static void main(String[] args) {
            // Send urgent alert via SMS
            MessageSender sms = new SmsSender();
            Message alert = new UrgentMessage(sms);
            alert.send("Server CPU usage exceeded 90%!");
    
            // Send regular information via Email
            MessageSender email = new EmailSender();
            Message newsletter = new NormalMessage(email);
            newsletter.send("Weekly engineering updates are published.");
        }
    }

    Key Architectural Takeaways

    • Composition Over Inheritance: Avoids multi-level inheritance hierarchies and messy diamond problem dilemmas.
    • Runtime Flexibility: Different message sender channels can be swapped dynamically based on system rules or user configurations.
    • Seamless Extensibility: Introducing a new message type (such as EncryptedMessage) or transport medium (such as SlackSender) requires zero modifications to existing classes.

    Watch More Related Design Pattern Tutorials


    Click here to watch in Youtube : https://www.youtube.com/watch?v=Sqpgv1QMIPk

    Click the below Image to Enlarge
    Bridge Design pattern - Implementation [Send Message]














    Bridge Design pattern - Implementation [Send Message] - Class Diagram






















    MessageSender.java


    public interface MessageSender
    {
    public void sendMessage(String message);
    }

    SmsMessageSender.java

    public class SmsMessageSender implements MessageSender
    {
    public void sendMessage(String message)
    {
    System.out.println("'"+message+ "'   : This Message has been sent using SMS");
    }
    }

    EmailMessageSender.java

    public class EmailMessageSender implements MessageSender
    {
    public void sendMessage(String message)
    {
    System.out.println("'"+message+ "'   : This Message has been sent using Email");
    }
    }

    Message.java

    abstract class Message
    {
    protected MessageSender messageSender;

    abstract public void sendMessage(String message);

    }

    ShortMessage.java

    public class ShortMessage extends Message
    {
    public ShortMessage(MessageSender messageSender)
    {
    super.messageSender = messageSender;
    }
    @Override
    public void sendMessage(String message)
    {
    if(message.length()<=5)
    {
    messageSender.sendMessage(message);
    }
    else
    {
    System.out.println("Sorry cannot send the message.....");
    }
    }

    }

    LongMessage.java

    public class LongMessage extends Message
    {

    public LongMessage(MessageSender messageSender)
    {
    super.messageSender = messageSender;
    }

    @Override
    public void sendMessage(String message)
    {
    messageSender.sendMessage(message);
    }

    }

    Client.java

    import java.util.Scanner;

    public class Client
    {

    public static void main(String[] args)
    {

    System.out.println("Do you want to send 'longmessage' or 'shortmessage' ?");
    Scanner scanner = new Scanner(System.in);
    String messageType = scanner.next();

    System.out.println("Please enter the message you want to send");
    Scanner scanner1 = new Scanner(System.in);
    String message = scanner1.nextLine();
    if (messageType.equalsIgnoreCase("longmessage"))
    {
    Message longMessage = new LongMessage(new EmailMessageSender());
    longMessage.sendMessage(message);
    }
    else
    {
    Message shortMessage = new ShortMessage(new SmsMessageSender());
    shortMessage.sendMessage(message);
    }

    }
    }

    Output

    Do you want to send 'longmessage' or 'shortmessage' ?
    longmessage
    Please enter the message you want to send
    Hello how are you ? when did you come?
    'Hello how are you ? when did you come?'   : This Message has been sent using Email

    Do you want to send 'longmessage' or 'shortmessage' ?
    shortmessage
    Please enter the message you want to send
    hi
    'hi'   : This Message has been sent using SMS

    See also:


  • Bridge Design pattern - Introduction
  • Bridge Design pattern - Real time example [Send Message]
  • Bridge Design pattern - Real time example [Publish Message]
  • Bridge Design pattern - Real time example [Shape]
  • Bridge Design pattern - Real time example [TV]
  • Bridge Design pattern - Class Diagram
  • Bridge Design pattern - Implementation [Shape]
  • Bridge Design pattern - Implementation [Publish Message]
  • Bridge Design pattern - Implementation [LED TV]
  • Bridge Design pattern - Keypoints
  • All Design Patterns Links
  • Friday, 17 January 2014

    Bridge Design pattern - Implementation [Shape]

    Master Software Architecture & Clean Code!

    Subscribe to Ram N Java for clean code, design pattern implementations, and practical Java tutorials!

    SUBSCRIBE NOW

    Decoupling Abstraction and Implementation

    The Bridge Design Pattern decouples an abstraction from its implementation so that both can vary independently. In graphics and GUI libraries, combining shapes and rendering colors using standard inheritance leads to a combinatorial explosion of subclasses (e.g., RedCircle, BlueCircle, RedSquare, BlueSquare).

    By extracting color/rendering functionality into its own separate hierarchy and bridging it with the shape hierarchy via composition, both hierarchies can evolve freely without duplicating code.

    Complete Java Code Implementation

    Here is an end-to-end, object-oriented example demonstrating the classic Shape and Color Bridge implementation in Java:

    // 1. Implementor Interface
    interface Color {
        void applyColor();
    }
    
    // 2. Concrete Implementors
    class RedColor implements Color {
        @Override
        public void applyColor() {
            System.out.println("Applying Red Color.");
        }
    }
    
    class BlueColor implements Color {
        @Override
        public void applyColor() {
            System.out.println("Applying Blue Color.");
        }
    }
    
    // 3. Abstraction (Bridge holding the Implementor reference)
    abstract class Shape {
        protected Color color;
    
        public Shape(Color color) {
            this.color = color;
        }
    
        public abstract void draw();
    }
    
    // 4. Refined Abstractions
    class Circle extends Shape {
        public Circle(Color color) {
            super(color);
        }
    
        @Override
        public void draw() {
            System.out.print("Drawing Circle: ");
            color.applyColor();
        }
    }
    
    class Square extends Shape {
        public Square(Color color) {
            super(color);
        }
    
        @Override
        public void draw() {
            System.out.print("Drawing Square: ");
            color.applyColor();
        }
    }
    
    // 5. Client Application
    public class ShapeBridgeDemo {
        public static void main(String[] args) {
            // Draw a Red Circle
            Shape redCircle = new Circle(new RedColor());
            redCircle.draw();
    
            // Draw a Blue Circle
            Shape blueCircle = new Circle(new BlueColor());
            blueCircle.draw();
    
            // Draw a Red Square
            Shape redSquare = new Square(new RedColor());
            redSquare.draw();
        }
    }

    Key Architectural Advantages

    • Eliminates Subclass Proliferation: Avoids creating N × M classes; adding new shapes or colors requires only N + M classes.
    • Composition Over Inheritance: Binds abstractions and implementors at runtime rather than compile-time.
    • Adheres to Open/Closed Principle: Adding a new color (e.g., GreenColor) or new shape (e.g., Triangle) requires no changes to existing classes.

    Watch More Related Design Pattern Tutorials


    Click here to watch in Youtube : https://www.youtube.com/watch?v=ztdhlaWL5S0

    Click the below Image to Enlarge
    Bridge Design pattern - Implementation [Shape]
















    Bridge Design pattern - Implementation [Shape] - Class Diagram


















    Shape.java


    abstract class Shape
    {

    protected ColorImplementor color;

    protected ColorImplementor getColor()
    {
    return color;
    }

    protected void setColor( ColorImplementor color )
    {
    this.color = color;
    }

    abstract public void colorIt();

    abstract public void draw();
    }

    Circle.java

    public class Circle extends Shape
    {

    public void colorIt()
    {
    System.out.print("Circle filled with ");
    color.fillColor();
    }

    @Override
    public void draw()
    {
    System.out.println("Circle has been drawn with out any color");
    }
    }

    Rectangle.java

    public class Rectangle extends Shape
    {

    public void colorIt()
    {
    System.out.print("Rectangle filled with ");
    color.fillColor();
    }

    @Override
    public void draw()
    {
    System.out.println("Rectangale has been drawn with out any color");
    }
    }

    ColorImplementor.java

    public interface ColorImplementor
    {
    public void fillColor();
    }

    BlueColorImplementor.java

    public class BlueColorImplementor implements ColorImplementor
    {
    public void fillColor()
    {
    System.out.println("blue color using BlueColorImplementor");
    }
    }

    GreenColorImplementor .java

    public class GreenColorImplementor implements ColorImplementor
    {
    public void fillColor()
    {
    System.out.println("green color using GreenColorImplementor");
    }
    }


    BridgeDesignPatternClient.java

    import java.util.Scanner;

    public class BridgeDesignPatternClient
    {

    public static void main( String[] args )
    {

    System.out.println("Please enter the color you want to fill  : 'Green' or 'Blue'");
    Scanner scanner = new Scanner(System.in);
    String color = scanner.next();
    System.out.println("color : " + color);

    Shape rectangleShape = new Rectangle();
    rectangleShape.draw();
    Shape circleShape = new Circle();
    circleShape.draw();
    System.out.println();
    if( "blue".equalsIgnoreCase(color) )
    {
    rectangleShape.setColor(new BlueColorImplementor());
    rectangleShape.colorIt();

    circleShape.setColor(new BlueColorImplementor());
    circleShape.colorIt();

    }
    else if( "green".equalsIgnoreCase(color) )
    {
    rectangleShape.setColor(new GreenColorImplementor());
    rectangleShape.colorIt();

    circleShape.setColor(new GreenColorImplementor());
    circleShape.colorIt();
    }

    }
    }

    Output

    Please enter the color you want to fill  : 'Green' or 'Blue'
    Green
    color : Green
    Rectangale has been drawn with out any color
    Circle has been drawn with out any color

    Rectangle filled with green color using GreenColorImplementor
    Circle filled with green color using GreenColorImplementor


    Please enter the color you want to fill  : 'Green' or 'Blue'
    Blue
    color : Blue
    Rectangale has been drawn with out any color
    Circle has been drawn with out any color

    Rectangle filled with blue color using BlueColorImplementor
    Circle filled with blue color using BlueColorImplementor


    See also:

  • Bridge Design pattern - Introduction
  • Bridge Design pattern - Real time example [Send Message]
  • Bridge Design pattern - Real time example [Publish Message]
  • Bridge Design pattern - Real time example [Shape]
  • Bridge Design pattern - Real time example [TV]
  • Bridge Design pattern - Class Diagram
  • Bridge Design pattern - Implementation [Send Message]
  • Bridge Design pattern - Implementation [Publish Message]
  • Bridge Design pattern - Implementation [LED TV]
  • Bridge Design pattern - Keypoints
  • All Design Patterns Links
  • Bridge Design pattern - Real time example [TV]

    Master Software Architecture & Clean Code!

    Subscribe to Ram N Java for clean code, design pattern implementations, and practical Java tutorials!

    SUBSCRIBE NOW

    Understanding the Bridge Pattern with TV & Remote

    The Bridge Design Pattern separates an abstraction from its implementation so that both can evolve independently. Instead of relying on rigid, deep inheritance hierarchies that combine every remote control type with every television brand, the Bridge pattern decouples the two using object composition.

    In this classic real-time example, the Remote Control acts as the abstraction layer (defining user operations), while the TV device serves as the implementation layer (executing brand-specific commands).

    Complete Java Code Walkthrough

    Here is an end-to-end, clean implementation showing how the TV device implementation connects to the remote abstraction:

    // 1. Implementor Interface
    interface TV {
        void on();
        void off();
        void tuneChannel(int channel);
    }
    
    // 2. Concrete Implementors
    class SonyTV implements TV {
        @Override
        public void on() {
            System.out.println("Sony TV is switched ON.");
        }
        @Override
        public void off() {
            System.out.println("Sony TV is switched OFF.");
        }
        @Override
        public void tuneChannel(int channel) {
            System.out.println("Sony TV tuned to channel: " + channel);
        }
    }
    
    class LGTV implements TV {
        @Override
        public void on() {
            System.out.println("LG TV is switched ON.");
        }
        @Override
        public void off() {
            System.out.println("LG TV is switched OFF.");
        }
        @Override
        public void tuneChannel(int channel) {
            System.out.println("LG TV tuned to channel: " + channel);
        }
    }
    
    // 3. Abstraction (Bridge holding the Implementor reference)
    abstract class Remote {
        protected TV tv;
    
        public Remote(TV tv) {
            this.tv = tv;
        }
    
        public abstract void powerOn();
        public abstract void powerOff();
        public abstract void changeChannel(int channel);
    }
    
    // 4. Refined Abstraction
    class SmartRemote extends Remote {
        public SmartRemote(TV tv) {
            super(tv);
        }
    
        @Override
        public void powerOn() {
            tv.on();
        }
    
        @Override
        public void powerOff() {
            tv.off();
        }
    
        @Override
        public void changeChannel(int channel) {
            tv.tuneChannel(channel);
        }
    }
    
    // 5. Client Application
    public class TVBridgeDemo {
        public static void main(String[] args) {
            // Control a Sony TV with SmartRemote
            TV sony = new SonyTV();
            Remote remote = new SmartRemote(sony);
            remote.powerOn();
            remote.changeChannel(7);
            remote.powerOff();
    
            System.out.println("--------------------");
    
            // Switch to an LG TV using the same abstraction
            TV lg = new LGTV();
            Remote lgRemote = new SmartRemote(lg);
            lgRemote.powerOn();
            lgRemote.changeChannel(21);
            lgRemote.powerOff();
        }
    }

    Key Architectural Benefits

    • Avoids Class Explosion: Prevents having to build distinct subclasses for every combination of remote and manufacturer (e.g., SonySmartRemote, LGSmartRemote).
    • Loose Coupling: Abstraction logic and device implementations can be updated, extended, or tested independently.
    • Runtime Swapping: Client code can reassign or swap underlying TV implementations on the fly without breaking remote functionality.

    Watch More Related Design Pattern Tutorials


    Click here to watch in Youtube : https://www.youtube.com/watch?v=qOVAIVt1dkA

    Click the below Image to Enlarge
    Bridge Design pattern - Real time example [TV]

















    See also:

  • Bridge Design pattern - Introduction
  • Bridge Design pattern - Real time example [Send Message]
  • Bridge Design pattern - Real time example [Publish Message]
  • Bridge Design pattern - Real time example [Shape]
  • Bridge Design pattern - Class Diagram
  • Bridge Design pattern - Implementation [Shape]
  • Bridge Design pattern - Implementation [Send Message]
  • Bridge Design pattern - Implementation [Publish Message]
  • Bridge Design pattern - Implementation [LED TV]
  • Bridge Design pattern - Keypoints
  • All Design Patterns Links
  • Bridge Design pattern - Real time example [Shape]

    Master Software Architecture & Clean Code!

    Subscribe to Ram N Java for clean code, design pattern implementations, and practical Java tutorials!

    SUBSCRIBE NOW

    The Shape & Color Problem in Object-Oriented Design

    The Bridge Design Pattern solves one of the most classic challenges in object-oriented programming: class explosion caused by multi-dimensional inheritance. Imagine having geometric shapes (like Circles and Rectangles) and color representations (such as Red and Blue).

    Using traditional inheritance, you would need classes like RedCircle, BlueCircle, RedRectangle, and BlueRectangle. If you introduce more shapes or colors, the number of required classes multiplies rapidly. The Bridge pattern breaks this inheritance chain by separating shapes (abstraction) from colors (implementation) using object composition.

    Complete Java Code Walkthrough

    Here is an end-to-end, clean implementation showing how the Shape abstraction bridges to the Color implementor in Java:

    // 1. Implementor Interface
    interface Color {
        void applyColor();
    }
    
    // 2. Concrete Implementors
    class RedColor implements Color {
        @Override
        public void applyColor() {
            System.out.println("filled with Red color.");
        }
    }
    
    class BlueColor implements Color {
        @Override
        public void applyColor() {
            System.out.println("filled with Blue color.");
        }
    }
    
    // 3. Abstraction (Bridge holding the Implementor reference)
    abstract class Shape {
        protected Color color;
    
        // Composition Bridge
        public Shape(Color color) {
            this.color = color;
        }
    
        public abstract void draw();
    }
    
    // 4. Refined Abstractions
    class Circle extends Shape {
        public Circle(Color color) {
            super(color);
        }
    
        @Override
        public void draw() {
            System.out.print("Drawing Circle ");
            color.applyColor();
        }
    }
    
    class Rectangle extends Shape {
        public Rectangle(Color color) {
            super(color);
        }
    
        @Override
        public void draw() {
            System.out.print("Drawing Rectangle ");
            color.applyColor();
        }
    }
    
    // 5. Client Application
    public class BridgeShapeDemo {
        public static void main(String[] args) {
            // Red Circle
            Shape redCircle = new Circle(new RedColor());
            redCircle.draw();
    
            // Blue Rectangle
            Shape blueRectangle = new Rectangle(new BlueColor());
            blueRectangle.draw();
    
            // Blue Circle (flexible composition without subclassing!)
            Shape blueCircle = new Circle(new BlueColor());
            blueCircle.draw();
        }
    }

    Key Architectural Advantages

    • Prevents Combinatorial Explosion: Adding N shapes and M colors requires only N + M classes instead of N × M classes.
    • Composition Over Inheritance: Connects abstraction and implementor dynamically at runtime rather than locking them down at compile time.
    • Strict Adherence to Open/Closed Principle: New shapes or new color implementations can be introduced without modifying existing codebase components.

    Watch More Related Design Pattern Tutorials


    Click here to watch in Youtube : https://www.youtube.com/watch?v=bBcrJ_ivwnE

    Click the below Image to Enlarge
    Bridge Design pattern - Real time example [Shape]

















    See also:

  • Bridge Design pattern - Introduction
  • Bridge Design pattern - Real time example [Send Message]
  • Bridge Design pattern - Real time example [Publish Message]
  • Bridge Design pattern - Real time example [TV]
  • Bridge Design pattern - Class Diagram
  • Bridge Design pattern - Implementation [Shape]
  • Bridge Design pattern - Implementation [Send Message]
  • Bridge Design pattern - Implementation [Publish Message]
  • Bridge Design pattern - Implementation [LED TV]
  • Bridge Design pattern - Keypoints
  • All Design Patterns Links
  • Tutorials