`
yinhumy
  • 浏览: 31181 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JAVA 桥接模式

阅读更多

一. 从树谈起

基本上所有人都知道树这个概念。

稍微深究.NET本质的人会懂得,.NET有个对象树。

学习ASP.NET的人肯定会知道,Web上有个控件树。

哪怕是只学习过数据结构应付考试的大学生也会知道Tree这个概念。

二. 把需求扩展成树

举个我们最常用的Photoshop做例子。

在Photoshop中,有许多图形工具,比如星星,比如方形,再比如圆形等等。

在Photoshop中,不用多说,也有很多种颜色供我们选择。

于是就产生了,红色的星星,绿色的星星。红色的方形,绿色的方形等等。

看看所产生的树:

无标题

现在是三种图形,三种颜色,于是我们就一共去声明了九个类,当然我们还不算中间过程中的辅助父类。

如果我们现在是18种图形,12种颜色,那么我们就需要写18*12个类,然后加上12个颜色的类和一个总父类,一共我们需要12*18+12+1=229个类。

让我们记住这个数字。

希望大家不要和我抬杠说,我们可以把颜色写成Color然后动态传入。我们这里是假设并不存在Color这个属性,而需要我们自己去实现。

三. 对象爆炸

这个词我已经在两个设计模式中提到了。

<重温设计模式(一)——享元模式> 中,我就用到了这个词。

当然,这里的爆炸并没有上篇文章中的那么恐怖。

但是追寻完美的我们也应该去改善他。

那就让我们开始想办法。

四. 多继承?

学习C++的我,第一个想到的是多继承。

用多继承描述这个模型再恰当不过了。 声明18个图形的类,然后声明12个颜色的类,然后用具体的图形类去多继承。

让我们看看这个表述图:

无标题

错综复杂的线看上去可能有些乱,但是我想大家应该都明白这个意思。

理解倒是容易理解了,可是这个时候我们再来看一下这个类的数量:

颜色12+颜色父类1+图形18+图形父类1+12*18,这个数字似乎比我们之前的那个数字还要大。

也许我会为他辩驳说他牺牲了空间而换取了可读性,但是可怜的C#不支持多继承?

五. 多继承为何被抛弃?

1. 从实际应用讲,B继承A并且重写了方法,C继承A并且重写了方法,那么这个时候D多继承了B和C,那么他究竟是继承B的方法还是C的方法呢?

2. 从面向对象角度讲,每个类只应有一个父类,就像说一个人只能有一个父亲一样。

但是多继承毕竟对我们来说还是比较易用的,他很容易理解,就像段中的颜色和图形一样。

抛弃多继承是从Java开始的,关于历史遗留的多继承问题,他们如何去解决呢?

让我们深入Java阵营内部去探索答案。

六. 深入Java阵营,寻找答案

方法一:用接口来取代继承,这个我不敢兴趣,从前我也知道,我想知道点别的。

方法二:实际上,在我们使用继承时,总有着一个主要继承点和次要继承点。然后我们应该分清主次,然后去继承那个主要继承点,然后用AOP去解决次要继承点的问题。

七. AOP+OOP == Complete OOP

AOP,面向切面编程,也称面向方面编程。大多数的设计模式都是在搞接口和外部之间的关系,而很少去深入类的内部去解决问题。AOP则是解决了这个问题。

举个例子,我们在做项目的时候常常需要去记录日志,那么这个日志常常是水平地分布在各个类中,但是其实这个日志功能与这个类的核心功能并无本质联系,这其实违背了对象的单一职责原则,更重要的使这些代码分散个各个角落,非常不容易维护。

AOP其实就是采用一种“横切”技术,深入对象的内部,然后将那些影响了多个类的功能写入一个模块,然后注入到各个类中。从而实现了功能的分离,这个常常用于日志管理,安全控制等次要继承点。

但是我在网上搜了一下,微软官方并未提供AOP框架技术,而都是些子实现框架,尚无Java的Spring之类广泛使用的标准。

八. 退而求其次

Spring的两个关键词:控制反转,依赖注入。

既然我们无法依赖注入,那么我们就普通注入吧。

废话这么多,让我们来步入正题:桥接模式。先来简单地看下结构图:

bridge

讲解之前,让我们先看看桥接模式的意思:将抽象部分与实现部分相分离,使他们都可以相互变化。

九. 代码演化

让我来先讲解一下这个模式的大概思路。

仍然用上面的例子做讲解,按照桥接模式,我们应该把所有可变化的点给抽离出来,然后组合到稳定的部分。先看看代码吧。



class Program
{
    static void Main(string[] args)
    {
        PhotoShop ps = new PhotoShop(new RedColor(),
 new Star());
        ps.Draw();
    }
}
interface IColor { }
class RedColor : IColor { }
class BlueColor : IColor { }
class YellowColor : IColor { }

interface IGraphics { }
class Rectangle:IGraphics { }
class Star:IGraphics { }
class Round : IGraphics { }

class PhotoShop
{
    IColor color;
    IGraphics graphics;
    public PhotoShop(IColor c, IGraphics g)
    {
        this.color = c;
        this.graphics = g;
    }
    public void Draw()
    {
        Console.WriteLine(color.GetType().ToString());
        Console.WriteLine(graphics.GetType().ToString());
    }
} 

image

这个时候的结构图应该是这样的:

无标题

这个时候让我们来计算一下类的总数:

12个颜色类+18个图形类+1个我们的图形=31个类。是不是很少呢?

十. 探微而知著,追本而溯源

世间本没有路,走得人多了,也便成了路。

其实世间本没有模式,只是原则总结了,便成了模式。

模式是可以衍生的,而原则是相对稳定的,那就让我们从这个模式中去挖掘原则。

在文章伊始,我们想到的都是什么?面向对象三原则继承多态封装中的第一个:继承。于是引发了对象爆炸。而用组合,解决了这个问题。

还记得一个很老套的面试题,抽象类和接口的区别。

那就让我们从这个面试题谈起:

1. 接口是行为的契约,而抽象类是特征的抽象。一个是can do,一个是is a。

2. 面向对象设计原则说:组合优于继承。

好了,让我们来看第二点,为什么说组合优于继承,而不说组合取代继承呢?

让我们继续向下看。

十一. 精益求精

组合优于继承,而不是组成取代继承。

上面的代码,如果不仅仅要求颜色和形状,还要求更多,那么我就要写很多很多的属性,好麻烦。

而且更重要的是,如果有这样的需求,我现在有12种颜色,然后有3种形状,分别是方形,圆形和星星,有两种 笔,分别是铅笔和蜡笔。但是我现在铅笔只对应方形和星星,蜡笔只对应圆形和星星。也就是说不存在圆形铅笔和方形蜡笔。这样的话我的组合不是浪费了么?而且 客户很可能组合错呀?

无标题

是的,不要一味去考虑组合。再重复一次我很爱说的话:模式是为了变化,不要为了模式而模式,我们只需要抽离出变化点就可以了!

如果这样,那我们就写好稳定的部门,有两种选择:

无标题

或者是把颜色的作为父类,这个就是看我们个人的选择了。

这样下来,假设说有很多的类,但是我们只有少数的选择,是不是我们的类更少了呢?

十二. 有一种能力叫做取舍

这句话是我在<Javascript王者归来>上看到的,原文用于HTML在Web标准上的选择遵循上。

这里我想说,桥接模式难并不是难在理解,而是难在应用。难在我们怎么去抽取出这个变化点,而保留住我们稳定点。

这个就是设计人员的取舍能力了!

十三. 举一而反三——工厂还是不工厂

工厂模式,这个我相信大家都在熟悉不过了。

去掉丑陋的if-else,然后用工厂给独立成为类。

应对数据库的变化,用抽象工厂+反射+web.config去搞定不同数据访问层。

应对不同验证方式,用工厂+反射。

这几乎成了Petshop的所有层通用的东西。但是在我们的项目中,真的需要这样么?

首先受if-else,他丑陋在哪里,是因为一旦我们引入了新的逻辑条件,就需要修改源码重新编译。

然后是数据库和验证方式,我想,几乎很少有公司真的去修改数据库和他们所习惯的产品的验证方式。

如果是这样,也就是说这些都是固定的,那么我们还有必要为了模式而模式地去用工厂么?

十四.  桥接总结

桥接模式(Bridge pattrern):将抽象部分与实现部分向分离,使他们都可以独立变化。

分享到:
评论
10 楼 fantasycs 2010-12-23  
写的挺不错的哈!

“将抽象部分与实现部分向分离,使他们都可以独立变化。”

抽象部分应该是:抽象了怎么去组合的部分。
实现部分应该是:颜色的具体实现,形状的具体实现...。
9 楼 liuyizhang 2010-02-09  
好像你static void main(String argsp[])
写的有点问题
应该是public static void main(String args[])
这是程序执行入口,固定写法
8 楼 jciwolf 2010-02-05  
首先强烈控诉发帖前要回答问卷,有必要吗,看来javaeye要没落了。
.net有enterpriselib里有aop,
另楼主举的例子像是策略模式。
7 楼 netrice 2010-02-04  
好文...~
6 楼 tedeyang 2010-02-04  
楼主适合讲述。
花了这么多时间,很好的普及了基础知识,可以送你十万功德分。
5 楼 hesy_007 2010-02-04  
不管怎么说,图文并茂是个优点。
4 楼 tianmo2008 2010-02-04  
请问....你是<<死神>>里的 朽木露琪亚 女士吗?
3 楼 akunamotata 2010-02-04  
你画的图好点点点啊...
2 楼 lich0079 2010-02-04  
spring 的 IOC 和 DI 指的是同一回事吧
2个关键词 IOC AOP 貌似更好
1 楼 ballanfeng 2010-02-04  
没有怎么理解...,我是这样想的不知道对不对,把变化点抽出一个抽象类,非变化的定义为接口,子类继承抽象类实现接口是不是这样?

相关推荐

    java桥接模式java桥接模式.doc

    【Java桥接模式】是一种设计模式,用于将抽象部分与实现部分分离,使得它们可以独立进行变化。在上述场景中,我们看到一个典型的桥接模式应用:发送提示消息功能。 1. 场景问题: - 发送提示消息功能涉及到不同...

    桥接模式和策略模式的区别,内含可运行代码和两者详细区别

    桥接模式和策略模式是软件设计模式中的两种重要模式,它们在实现上有着相似之处,但各自的应用场景和设计理念有所不同。下面将详细阐述这两种模式的特点、区别以及它们在实际编程中的应用。 首先,桥接模式(Bridge...

    java桥接模式

    ### Java桥接模式详解 #### 一、桥接模式简介 桥接模式(Bridge Pattern)是一种结构型设计模式,它的核心思想是将抽象与其实现分离,使它们都可以独立变化。这种模式允许用户在不影响其他部分的情况下改变某些...

    设计模式之桥接模式

    在Java中,桥接模式的实现通常涉及以下步骤: 1. 定义Implementor接口,如`Color`接口,包含绘制颜色的方法。 2. 创建具体实现类,如`RedColor`和`BlueColor`,实现`Color`接口。 3. 定义Abstraction接口,如`Shape`...

    JAVA桥接模式.doc

    在Java中,桥接模式通常用于处理类的膨胀问题,特别是当有多个维度的分类或者组合时,避免过度的类数量爆炸。 在描述中提到的场景是一个Photoshop图形工具的例子,其中有各种形状(如星星、方形、圆形)和多种颜色...

    Java桥接模式原理及用法解析

    Java 桥接模式原理及用法解析 Java 桥接模式是一种结构型设计模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型...

    java 桥接模式

    让我们深入探讨一下桥接模式的原理、应用场景以及如何在Java中实现。 **桥接模式的核心思想** 1. **分离接口与实现**:桥接模式将抽象接口与其实现分离开来,使得两者可以独立变化。这样,当需要改变一个部分时,...

    java常用设计模式-桥接模式

    Java 桥接模式 设计模式 桥接模式(Bridge Pattern)是一种常用的设计模式,它将抽象化和实现化解耦,使用封装、聚合以及继承等基本技术,将两个独立变化的维度通过抽象化的方式进行桥接,从而降低了它们之间的耦合...

    23种设计模式(9) java桥接模式

    Java桥接模式详解 Java桥接模式是一种结构式设计模式,它的主要作用是将抽象部分与实现部分分离,使它们都可以独立的变化。桥接模式可以在程序运行期间动态地设置抽象部分需要用到的具体的实现,还可以动态切换具体...

    桥接模式java示例代码

    桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立进行变化。在Java中,这种模式常用于降低复杂系统的设计耦合性,提高系统的可扩展性和可维护性。刘伟老师的《设计模式》一书中的桥接模式...

    Java桥接模式实例详解【简单版与升级版】

    总结,Java桥接模式通过抽象部分与实现部分的解耦,提供了更高的灵活性和可扩展性。在上述实例中,`Meal` 类作为抽象部分,`MealImp` 接口及其实现类作为实现部分,共同构建了一个允许动态组合不同餐饮文化的框架。...

    Bridge 桥接模式(结构型模式)

    4. 代码实现,展示如何在编程语言中实现桥接模式,可能包括Java、C#或Python等。 5. 桥接模式与其他设计模式的对比,如装饰器模式、适配器模式等。 6. 桥接模式的优缺点分析,以及在实际项目中的应用示例。 7. 如何...

    java设计模式-桥接模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段...

    轻松掌握Java桥接模式

    总结起来,Java 桥接模式的关键在于将抽象和实现分离,通过组合的方式降低类之间的耦合度,提高代码的可读性和可维护性。在实际项目中,当面临多种抽象和实现需要组合时,考虑使用桥接模式能够简化设计,便于后续的...

    Java设计模式之桥接模式

    桥接模式(Bridge Pattern),将抽象部分与它的实现部分分离,使它们都可以独立地变化。更容易理解的表述是:实现系统可从多种维度分类,桥接模式将各维度抽象出来,各维度独立变化,之后可通过聚合,将各维度组合...

    java设计模式之桥接模式(Bridge)

    在Java编程中,桥接模式可以帮助我们处理多维度的变化,避免过度使用继承导致的类爆炸问题。 在桥接模式中,有四个主要的角色: 1. **抽象化(Abstraction)**:定义抽象接口,提供高层的业务逻辑,它引用实现化...

    设计模式 - 桥接模式

    桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立进行变化。这种模式在软件工程中被广泛应用于处理组件之间的耦合问题,使得系统具有更好的可扩展性和灵活性。 桥接模式的主要组成部分...

    Android桥接模式demo

    **Android桥接模式详解** 桥接模式是一种设计模式,它将抽象部分与实现部分分离,使得它们可以独立地进行变化。在Android开发中,尤其是在构建可扩展和灵活的架构时,这种模式尤其有用。本文将深入探讨桥接模式在...

    设计模式之桥接模式,内含可运行代码

    桥接模式是软件设计模式中的一种结构型模式,它的主要目的是为了实现抽象和实现的解耦,使得两者可以独立地进行扩展。在桥接模式中,抽象类(Abstraction)不直接引用具体实现(Implementation),而是通过一个桥接...

Global site tag (gtag.js) - Google Analytics