Java 传统桥接模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yqj2065/article/details/38970097

注,本文是我早期写的,避免类型爆炸发介绍桥接模式,没有抓住桥接模式的本质——在策略中提供策略yqj2065不想修改它了,留下来作为大家嘲笑的靶子。

桥接模式的本质是将2次以上的策略选择加以串接。特别在复合函数的例子中,桥接模式的“抽象与它的实现”可以是同一个接口F——当然,你也可以说复合函数使用的,是装饰模式

参考桥接模式和嵌套lambda表达式



桥接模式(bridge pattern)是一种策略式委派方式,其主要目标是避免类型爆炸

问题描述:假设类Client(例如Client表示一个会所)将对人/Person进行统一的处理,而Person类层次有(以人的职业划分其子类)教师、医生、律师……,另外,系统还需要将Person按照“地域” (或按年龄、收入……)划分,那么处于“武汉教师”、“广州律师”地位的类,其个数将等于地域的子类个数与Person(按职业划分的)子类个数的乘积。

如何控制“武汉-教师”等等这些类型的数量而且还能够对他们统一的作为Person处理呢?

5.4.1 替代多继承性

多继承性普遍存在。类型X与许多的概念/类型之间存在Is-A关系,而且它的这些父类型彼此并没有必然联系,每一个父类型仅仅描述X的一个方面,X需要(应该)继承多个父类才是适当的设计。例如Person(的职业)与地域/Region (还可以有年龄、收入等类层次),是独立的、无关的类型层次,则“武汉教师”与它们都存在As-A关系。但是,Java中不允许类的多继承,一个可能的设计方案是:以Person类层次为基础时,将Region设计成接口,为每一种职业都提供一套各种地域版本。10个职业,来自30个地方,则需要300个类——类型爆炸。为了控制类型爆炸,可以以Person(的职业) 为主(主体类),而将另一个类型(辅助类)Region作为主体类的成员变量

package delegate.bridge;
/**
 * @author yqj2065
 * @version 0.1
 */
public abstract class Person{
    protected Region where;
    public void setRegion(Region where)	{//依赖注入或任意其他初始化方式
        this.where = where;
    }
    //按照职业风格和方言介绍自己
    public abstract void show();
}
package delegate.bridge;
public interface Region{
    public void say(String style);
}
<pre name="code" class="java">package delegate.bridge;
public class WHer implements Region {
    @Override public void say(String style){
   System.out.println(style+"说:您呀好");
}
package delegate.bridge;
public class Teacher extends Person{
	@Override public void show(){
		String myStyle="带着粉笔灰的味道";
		this.where.say(myStyle);
	}	
}
package delegate.bridge;
import tool.God;
public class Client{
	public static void test(){
		Person p = (Person)God.create("Teacher");
		p.setRegion( (Region)God.create("Region") );
	    p.show();
	}
}

这一结构,使得系统中类的数量极大地减少。10个职业,来自30个地方,则需要10+30个类。

值得注意的是,(为每一种职业都提供一套各种地域版本)300个类的时候,每个类的say()方法有自己任一的版本;而在10+30类的时候,不在有300种say()。原来的完整的方法体被分成了两个阶段,作为Person.show(),所有的老师(不管是哪里的),将按照show()的代码反映其职业特点;而后调用Region.say(),不同的地域有自己的代码块。因此,两个阶段的代码块组合成10*30种方法体。
桥接模式中,外界接触的是Person的接口show(),而Region.say()某种程度上意味着show()的实现部分

5.4.2 桥接的作用

[GoF]关于桥接模式意图的描述,即"decouple anabstraction from its implementation so that the two can varyindependently".(将抽象与它的实现分离,使它们都可以独立地变化),我认为是较难理解的。“抽象与它的实现分离”,少见的表达。抓狂,看《设计模式》的这一节,太累人了,不知道为什么那么别扭。

按照[编程导论]的术语体系,桥接的定义如下:

★桥接模式控制类型爆炸,通过辅助类使得主体类的方法多态化

1. show()方法的实现被多态化

主体类Person有教师、医生、律师……子类,它的方法show(),如果不调用地域/Region的say(),每一种子类如Teacher——虽然(每个子类)有不同的实现方式,但是每个子类的实现是固定的。除非Teacher派生WHTeacher或GDTeacher,才使得Teacher. show()有多种实现。

在桥接模式中,show()的方法体中由于调用了Region.say(),按照Region指向对象的实际类型,使得show()的实现可以在运行时刻进行配置(甚至可以在运行时刻改变它的实现)。

桥接模式的主要优点源于多态的优点。

①主体类和辅助类可以独立地变化,此变化指遵循OCP的“两者都可以通过派生子类加以扩展”。按照Client代码的演示,Person与Region的子类可以进行任意的组合。

②外界接触的是Person的接口show()。

③桥接模式将多个独立维度可能导致的笛卡尔积式类型爆炸转换成辅助类的子类型的累积和。

其他,想到了再加。



最后编辑时间:2016.11.26


阅读更多

没有更多推荐了,返回首页