专栏首页Jed的技术阶梯Java设计模式之桥梁模式

Java设计模式之桥梁模式

梦想中的我自己,身价过亿,有两个大公司,一个是房地产公司,一个是服装制造公司,其实是什么公司我倒是不关心,我关心的是它赚不赚钱,赚了多少,这才是我关心的。先用类图表示一下我这两个公司:

代码如下:

public abstract class Corp {
    
    protected abstract void product();
    protected abstract void sell();
    
    /**
     * 先生产,再销售
     */
    public void makeMoney() {
        this.product();
        this.sell();
    }

}
public class HouseCorp extends Corp {

    @Override
    protected void product() {
        System.out.println("承建XX市XX小区...");
    }

    @Override
    protected void sell() {
        System.out.println("首付20万,海景别墅任意挑!");
    }
    
    @Override
    public void makeMoney() {
        super.makeMoney();
        System.out.println("房地产公司赚大钱咯!");
    }

}
public class ClothCorp extends Corp {

    @Override
    protected void product() {
        System.out.println("低奢新品牌服饰首发...");
    }

    @Override
    protected void sell() {
        System.out.println("买两件一件!");
    }
    
    @Override
    public void makeMoney() {
        super.makeMoney();
        System.out.println("服装公司赚小钱...");
    }

}

两个公司都有了,我肯定会关心两个公司的运营情况,我要知道它是生产什么的,赚多少钱,Client代码如下:

public class Client {

    public static void main(String[] args) {
        System.out.println("-------房地产公司是这个样子运行的-------");
        HouseCorp houseCorp = new HouseCorp();
        houseCorp.makeMoney();
        System.out.println();

        System.out.println("-------服装公司是这样运行的-------");
        ClothCorp clothCorp = new ClothCorp();
        clothCorp.makeMoney();
    }

}

运行结果:
-------房地产公司是这个样子运行的-------
承建XX市XX小区...
首付20万,海景别墅任意挑!
房地产公司赚大钱咯!

-------服装公司是这样运行的-------
低奢新品牌服饰首发...
买两件一件!
服装公司赚小钱...

我发现,服装公司赚的小钱满足不了我,我打算把服装公司改为IPad公司,修改类图如下:

IPad公司的代码如下:

public class IPadCorp extends Corp {

    @Override
    protected void product() {
        System.out.println("新IPad配置大升级!");
    }

    @Override
    protected void sell() {
        System.out.println("新IPad6期分期免息,还在等什么?");
    }
    
    @Override
    public void makeMoney() {
        super.makeMoney();
        System.out.println("苹果的产品果然赚钱!");
    }

}

为了查看公司运营情况,还需要修改Client的代码:

public class Client {

    public static void main(String[] args) {
        System.out.println("-------房地产公司是这个样子运行的-------");
        HouseCorp houseCorp = new HouseCorp();
        houseCorp.makeMoney();
        System.out.println();

        System.out.println("-------服装公司是这样运行的-------");
        IPadCorp ipadCorp = new IPadCorp();
        ipadCorp.makeMoney();
    }

}

确实,只用修改了几句话,我的服装厂就开始变成iPad生产车间,但是我制造了IPad,就不能制造服装了啊,那我以后想要制造MP4,改装后我的IPad就不能生产了啊,这样不行,成本太高了,于是我们修改一下类图:

代码如下:

/**
 * 整个公司的产品类
 */
public abstract class Product {
    
    public abstract void beProducted();
    public abstract void beSelled();

}
/**
 * 公司盖的房子
 */
public class House extends Product {

    @Override
    public void beProducted() {
        System.out.println("承建XX市XX小区...");
    }

    @Override
    public void beSelled() {
        System.out.println("首付20万,海景别墅任意挑!");
    }

}
/**
 * 公司制造的服装
 */
public class Cloth extends Product {

    @Override
    public void beProducted() {
        System.out.println("低奢新品牌服饰首发...");
    }

    @Override
    public void beSelled() {
        System.out.println("买两件送一件!");
    }

}
/**
 * 公司制造的IPad
 */
public class IPad extends Product {

    @Override
    public void beProducted() {
        System.out.println("新IPad配置大升级!");
    }

    @Override
    public void beSelled() {
        System.out.println("新IPad6期分期免息,还在等什么?");
    }

}
/**
 * 公司的抽象类
 */
public abstract class Corp {
    
    // 定义一个产品对象,具体是什么还不知道
    private Product product;
    
    // 构造函数,由子类定义传递具体的产品进来
    public Corp(Product product) {
        this.product = product;
    }
    
    // 赚钱的方式肯定都是一样的
    public void makeMoney() {
        this.product.beProducted();
        this.product.beSelled();
    }

}
/**
 * @description: 房地产公司盖房子
 */
public class HouseCorp extends Corp {
    
    public HouseCorp(House house) {
        super(house);
    }

    @Override
    public void makeMoney() {
        super.makeMoney();
        System.out.println("房地产公司赚大钱咯!");
    }

}
/**
 * @description: 制造公司搞制造,具体生产什么还不知道
 */
public class MakeCrop extends Corp {

    /**
     * 制造什么产品,等被调用的时候才知道
     */
    public MakeCrop(Product product) {
        super(product);
    }
    
    @Override
    public void makeMoney() {
        super.makeMoney();
        System.out.println("造啥都能赚钱!");
    }

}

HouseCorp类和MakeCorp类的区别是在有参构造的参数类型上,HouseCorp类比较明确,我就是只要House类,所以直接定义传递进来的必须是House类,一个类尽可能少的承担职责,那方法也是一样,既然HouseCorp类已经非常明确只生产House产品,那为什么不定义成House类型呢?MakeCorp就不同了,它是确定不了生产什么类型。

Client代码如下:

public class Client {

    public static void main(String[] args) {
        System.out.println("-------房地产公司是这个样子运行的-------");
        House house = new House();
        HouseCorp houseCorp = new HouseCorp(house);
        houseCorp.makeMoney();
        System.out.println();

        System.out.println("-------制造公司是这样运行的-------");
        MakeCorp makeCorp = new MakeCorp(new Cloth());
        makeCorp.makeMoney();
    }

}

运行结果:
-------房地产公司是这个样子运行的-------
承建XX市XX小区...
首付20万,海景别墅任意挑!
房地产公司赚大钱咯!

-------制造公司是这样运行的-------
低奢新品牌服饰首发...
买两件送一件!
造啥都能赚钱!

而现在想让制造公司制造IPad,这就非常简单了,代码如下:

public class Client {

    public static void main(String[] args) {
        System.out.println("-------房地产公司是这个样子运行的-------");
        House house = new House();
        HouseCorp houseCorp = new HouseCorp(house);
        houseCorp.makeMoney();
        System.out.println();

        System.out.println("-------制造公司是这样运行的-------");
        // 把制造服装的公司改为制造IPad就这么简单
        // MakeCorp makeCorp = new MakeCorp(new Cloth());
        MakeCorp makeCorp = new MakeCorp(new IPad());
        makeCorp.makeMoney();
    }

}

看上面的代码,就修改了一句代码就完成了生产产品的转换。我们深入的思考一下,我现在只有房地产公司和制造公司,以后我还要开其他公司这么办?新增加公司对我们上面的类图没有大的修改,充其量是扩展:

  • 增加公司,要么继承Corp类,要么继承HouseCorp或MakeCorp,不用再修改原有的类了;
  • 增加产品,继承Product类,或者继承House类,你要把房子分为公寓房、别墅、商业用房等等;

你都是在扩展,唯一你要修改的就是Client类,也就是说Corp类和Product类都可以自由的扩展,而不会对整个应用产生太的变更,这就是桥梁模式。

为什么叫桥梁模式?我们看一下桥梁模式的通用类图:

看到中间那根带箭头的线了吗?是不是类似一个桥,连接了两个类?所以就叫桥梁模式。 我们再把桥梁模式的几个概念熟悉一下,我把Corp类以及它的两个实现类放到了Abstraction包中,把House以及相关的三个实现类放到了Implementor包中,这两个包分别对应了桥梁模式的业务抽象角色(Abstraction)和业务实现角色(Implementor),这两个角色大家只要记住一句话就成:业务抽象角色引用业务实现角色,或者说业务抽象角色的部分实现是由业务实现角色完成的,很简单,别想那么复杂了。

桥梁模式的优点就是类间解耦,我们上面已经提到,两个角色都可以自己的扩展下去,不会相互影响,这个也符合OCP原则。

本文原书: 《您的设计模式》 作者:CBF4LIFE

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java设计模式之工厂方法模式

    女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是“造人”的工作,这个词被现代人滥用了。这个故事是说,女娲在补了天后,下到凡间一看,哇塞,风...

    CoderJed
  • Java设计模式之策略模式

    刘备要到江东娶老婆了,走之前诸葛亮给赵云(伴郎)三个锦囊妙计,说是按天机拆开解决棘手问题,嘿,还别说,真是解决了大问题,搞到最后是周瑜陪了夫人又折兵呀,那咱们先...

    CoderJed
  • Java设计模式之迭代器模式

    老板让我打印各个项目的报表,包括项目名称,人数,开销等信息,这个好办,看下面的类图:

    CoderJed
  • 09(01)总结final,多态,抽象类,接口

    1:final关键字(掌握) (1)是最终的意思,可以修饰类,方法,变量。 (2)特点: A:它修饰的类,不能被继承。 B:它修饰的方法,不能被重写。 ...

    Java帮帮
  • 第五节:详细讲解Java中的接口与继承

    大家好,我是 Vic,今天给大家带来详细讲解Java中的接口与继承的概述,希望你们喜欢

    达达前端
  • TestNG用法概括

    应用场景:将通用的功能抽取并封装起来,在方法中使用注解@BeforeSuite和@AfterSuite,在测试类中继承这个类,测试类在运行前会先运行@Befor...

    桑鱼
  • SpringMVC快速使用AOP

    最近突然想到了AOP编程,于是在自己的SpringMVC小项目中引入了。AOP一般用来做些什么呢?这里简单的使用AOP做拦截日志,来介绍下在SpringMVC中...

    幽鸿
  • 设计模式之模板方法模式(一)

    学习了前面的朋友都知道,目前为止,我们的议题都是绕着封装转;我们已经封装了对象创建、方法调用、复杂接口、鸭子、比萨…那接下来呢?

    程序员小跃
  • Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

    在 Spring Boot 中已经移除了 web.xml 文件,如果需要注册添加 Servlet、Filter、Listener 为 Spring Bean,在...

    朝雾轻寒
  • Spring Boot 2.X(十):自定义注册 Servlet、Filter、Listener

    在 Spring Boot 中已经移除了 web.xml 文件,如果需要注册添加 Servlet、Filter、Listener 为 Spring Bean,在...

    朝雾轻寒

扫码关注云+社区

领取腾讯云代金券