桥接模式(Bridge Pattern)

Posted 街酒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了桥接模式(Bridge Pattern)相关的知识,希望对你有一定的参考价值。

抽象关联取代了传统的多重继承

模式动机

桥接模式(Bridge Pattern)是一种很实用的结构型模式,如果系统中某个类存在两个独立变化的维度,通过该模式可以将这两个维度分离出来,使得两者可以独立扩展。桥接模式用一种巧妙的方式处理多层继承存在的问题,用抽象关联取代了传统的多重继承,将类之间的静态继承关系转换为动态的对象组合关系,使得系统更加灵活,并易于扩展,同时有效地控制了系统中类的个数。

模式定义

将抽象部分与它的实现部分分离,使它们都可以独立地变化。

  • 对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式
  • 用抽象关联取代了传统的多层继承
  • 将类之间的静态继承关系转换为动态的对象组合关系

模式结构

案例实现

案例背景

毛笔:颜色和型号实现了分离,增加新的颜色或者型号对另一方没有任何影响

案例结构

代码实现

抽象类

public abstract class Pen 

    protected Color color;

    public void setColor(Color color) 
        this.color = color;
    

    public abstract void draw(String name);

细化抽象类

public class BigPen extends Pen 
    @Override
    public void draw(String name) 
        String penType = "大号毛笔绘制";
        this.color.bepaint(penType,name);
    

public class MiddlePen extends Pen 

    @Override
    public void draw(String name) 
        String penType = "中号毛笔绘制";
        this.color.bepaint(penType,name);
    

public class SmallPen extends Pen 
    @Override
    public void draw(String name) 
        String penType = "小号毛笔绘制";
        this.color.bepaint(penType,name);
    

接口

public interface Color 
    //用于图形着色的方法
    void bepaint(String penType,String name);


接口实现类

public class Red implements Color 
    @Override
    public void bepaint(String penType, String name) 
        System.out.println(penType+"红色的"+name+".");
    


public class White implements Color 
    @Override
    public void bepaint(String penType, String name) 
        System.out.println(penType+"白色的"+name+".");
    


public class Green implements Color 
    @Override
    public void bepaint(String penType, String name) 
        System.out.println(penType+"绿色的"+name+".");
    


public class Blue implements Color 
    @Override
    public void bepaint(String penType, String name) 
        System.out.println(penType+"蓝色的"+name+".");
    


public class Black implements Color 
    @Override
    public void bepaint(String penType, String name) 
        System.out.println(penType+"黑色的"+name+".");
    

客户类

public class Client 

    public static void main(String[] args) 

        Color color;
        Pen pen;
        color = (Color) XMLUtilPen.getBean("color");
        pen = (Pen) XMLUtilPen.getBean("pen");

        pen.setColor(color);
        pen.draw("鲜花");

    


实现结果

模式分析

  • 桥接模式中体现了很多OOP的思想,包括开闭原则合成复用原则里氏代换原则依赖倒转原则等。
  • 桥接模式可以从接口中分离实现功能,设计更具有扩展性。
  • 桥接模式减少了子类个数,代码简洁。
  • 重点理解如何将抽象化(Abstraction)和实现化(Implementation)脱耦,使得两者可以独立变化。
  • 脱耦
    • 抽象化和实现化之间的耦合解开,或者说是将强关联改换成弱关联,将两个角色之间的继承关系改为关联关系
    • 桥接模式中的所谓脱耦就是指在一个软件系统的抽象化和实现化之间使用关联关系(组合或者聚合)而不是继承关系,从而使得两者可以相对独立地变化。
    • 继承是强耦合关系。

总结

模式优点

  • 分离抽象接口及其实现部分
  • 可以取代多层继承方案,极大地减少了子类的个数
  • 提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,不需要修改原有系统,符合开闭原则

模式缺点

  • 会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就要针对抽象层进行设计与编程
  • 正确识别出系统中两个独立变化的维度并不是一件容易的事情

应用情形

  • 需要在抽象化和具体化之间增加更多的灵活性,避免在两个层次之间建立静态的继承关系
  • 抽象部分和实现部分可以以继承的方式独立扩展而互不影响
  • 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立地进行扩展
  • 不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统

模式扩展

桥接模式与适配器模式经常联合使用,适配器模式可以解决两个已有接口间不兼容的问题,适配器采用增加适配器的方式将第三方类集成到系统中;而桥接模式则通过接口继承或者类继承的方式对系统进行扩展。两个模式用于设计的不同阶段,通常情况下桥接模式用于系统的初步设计,对于存在两个独立变化维度的类可以将其分为抽象化和实现化两个角色,使它们可以分别进行变化。初步设计完成后,当发现系统与已有类无法协同工作时,可以采用适配器模式。

php桥接模式(bridge pattern)

有点通了

<?php
/*
The bridge pattern is used when we want to decouple a class or abstraction from its
implementation, allowing them both to change independently. This is useful when
the class and its implementation vary often
*/

interface MessagingInterface 
    public function send($body);


class TextMessage implements MessagingInterface 
    public function send($body) 
        echo "TextMessage > send > $body: <br/>";
    


class HtmlMessage implements MessagingInterface 
    public function send($body) 
        echo "HtmlMessage > send > $body: <br/>";
    


interface MailerInterface 
    public function setSender(MessagingInterface $sender);
    public function send($body);


abstract class Mailer implements MailerInterface 
    protected $sender;
    public function setSender(MessagingInterface $sender) 
        $this->sender = $sender;
    


class PHPMailer extends Mailer 
    public function send($body) 
        $body .= "\\n\\n Set from a phpmailer .";
        return $this->sender->send($body);
    


class SwiftMailer extends Mailer 
    public function send($body) 
        $body .= "\\n\\n Set from a swiftmailer .";
        return $this->sender->send($body);
    


$phpMailer = new PHPMailer();
$phpMailer->setSender(new TextMessage());
$phpMailer->send(‘Hi!‘);

$swiftMailer = new SwiftMailer();
$swiftMailer->setSender(new HtmlMessage());
$swiftMailer->send(‘Hello!‘);
?>

技术图片

以上是关于桥接模式(Bridge Pattern)的主要内容,如果未能解决你的问题,请参考以下文章

设计模式 -- 桥接模式(Bridge Pattern)

php桥接模式(bridge pattern)

桥接模式(Bridge Pattern)

C++设计模式——桥接模式(Bridge Pattern)

二十四种设计模式:桥接模式(Bridge Pattern)

9,桥接模式(Bridge Pattern)是将抽象部分与实际部分分离,使它们都可以独立的变化。