设计模式之桥接模式

        我们平时去面馆吃面,点面的时候有的人喜欢吃辣的面,有的喜欢微辣,有的喜欢无辣。对于面的种类还有的喜欢猪肉面、牛肉面等等。那么厨师肯定根据大家的点的情况进行煮。厨师肯定依据大家点的面种类,先将同类的进行煮,然后再进行添加辣的程度,这样有助于效率的提高。如果厨师一开始就煮辣的牛肉面,不辣的牛肉面。。。。。那么这样厨师肯定得忙不过来而且效率极低,可能还会被老板炒鱿鱼。而先将面先煮好,再决定辣的口味。这相当于将面里的菜和面的辣味程度抽象分离出来,然后这两者类层次建立关系就叫做桥接。桥接模式就是将抽象部分与它的实现部分分离,使它们可以独立地变化。

1.适用性和优缺点
1.适用性
a.你不希望在抽象和它的实现部分之间有一个固定的绑定关系。在程序运行时实现部分应可以被选择和切换,如辣的牛肉面是实现,而抽象是牛肉面。这里不通过继承将牛肉面与辣的牛肉面绑定在一起。
b.类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。桥接模式使你可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。这里面和辣味是两个抽象,它们都有自己具体实现,比如面有牛肉面、猪肉面,辣味有重辣、微辣、无辣等,然后通过将它们关联起来就可以扩充,变成辣的牛肉面、微辣的猪肉面等等。
c.对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。因为桥接模式是将抽象的接口对象传入实现部分的,所以即使抽象的实现部分发生代码修改,但针对接口编程并不影响。
d.你想在多个共享实现(可能使用引用计数),但同时要求客户并不知道这一点。
e.某个类具有两个或者两个以上的维度变化,如果只是使用继承无法实现这种需要,或者使得设计变得相当臃肿。例如面的例子中,面中的菜和辣味是两个维度变化,如果使用继承,将会使得设计变得非常臃肿。

2.优点
a.将实现的类层次与抽象的类层次解耦,通过关联的形式将两者联系在一起。就像牛肉面和辣味一般,相对比较灵活。
b.抽象和实现可以独立扩展,不会影响到对方。比如面和辣味可以拥有自己的实现类,这样可以使得各自独立扩展。
c.对于“具体的抽象类”所做的改变不会影响到客户,客户需要无辣的牛肉面,只需要牛肉面对象和无辣对象关联即可,并不关心牛肉面类是否发生改变。

3.缺点
桥接模式增加了系统的复杂度。

2.示例讲解
首先定义一个面的抽象类,为了给所有面统一接口,面中需要有一个辣的程度对象,正是这种组合将两者关联在一起。
package bridge;

public abstract class AbstractNoodle
{
	// 组合一个Peppery变量,用于将该维度的变化独立出来
	protected Peppery style;
	// 每份Noodle必须组合一个Peppery对象
	public AbstractNoodle(Peppery style)
	{
		this.style = style;
	}
	public abstract void eat();
}
接下来是牛肉面和猪肉面的实现
package bridge;

public class BeefNoodle extends AbstractNoodle
{
	public BeefNoodle(Peppery style)
	{
		super(style);
	}
	// 实现eat()抽象方法
	public void eat()
	{
		System.out.println("这是一碗美味的牛肉面条。"
			+ super.style.style());
	}
}
package bridge;

public class PorkyNoodle extends AbstractNoodle
{
	public PorkyNoodle(Peppery style)
	{
		super(style);
	}
	// 实现eat()抽象方法
	public void eat()
	{
		System.out.println("这是一碗稍嫌油腻的猪肉面条。"
			+ super.style.style());
	}
}
接下来是表示辣的程度的接口。

package bridge;

public interface Peppery
{
	String style();
}
具体类的实现
package bridge;

public class PepperySytle implements Peppery
{
	// 实现"辣味"风格的方法
	public String style()
	{
		return "辣味很重,很过瘾...";
	}
}
package bridge;

public class PlainStyle implements Peppery
{
	// 实现"不辣"风格的方法
	public String style()
	{
		return "味道清淡,很养胃...";
	}
}
最后将面的两个维度上因素组合起来,即将辣的程度对象放进面中,最后煮出面。

package bridge;

public class Test
{
	public static void main(String[] args)
	{
		// 下面将得到“辣味”的牛肉面
		AbstractNoodle noodle1 = new BeefNoodle(
			new PepperySytle());
		noodle1.eat();
		// 下面将得到“不辣”的牛肉面
		AbstractNoodle noodle2 = new BeefNoodle(
			new PlainStyle());
		noodle2.eat();
		// 下面将得到“辣味”的猪肉面
		AbstractNoodle noodle3 = new PorkyNoodle(
			new PepperySytle());
		noodle3.eat();
		// 下面将得到“不辣”的猪肉面
		AbstractNoodle noodle4 = new PorkyNoodle(
			new PlainStyle());
		noodle4.eat();
	}
}
运行程序结果如下:
这是一碗美味的牛肉面条。辣味很重,很过瘾...
这是一碗美味的牛肉面条。味道清淡,很养胃...
这是一碗稍嫌油腻的猪肉面条。辣味很重,很过瘾...
这是一碗稍嫌油腻的猪肉面条。味道清淡,很养胃...
        由上面过程可以发现,面的菜有两种,辣的程度有两种,便能组合成四种面。桥接模式就是将一个类的两个因素抽象分离,然后各自独立扩展实现类,最后根据需求进行组合。这里利用了组合,但跟组合模式不同,组合模式展示出来的是类树,即一个类中包含多少个子类。而桥接模式针对两个同一层次的类层次进行对象的组合。
        桥接模式的核心就是将一个类的两个或两个以上的维度抽象分离出来,并各自扩展,然后最终进行组合。就如同这里的面有两个影响因素,即菜和辣味,那么利用桥接模式,则应该先将菜和辣味分离出来,并相应扩展,然后对象组合,才有最终的辣的牛肉面,清淡的猪肉面等等。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值