[DP]Bridge设计模式

9 篇文章 0 订阅
8 篇文章 0 订阅

这次我们继续接着我们的KFGStoe连锁餐厅

我们的KFG连锁餐厅在全国各地都有连锁加盟,因为各地的口味风俗差异,所以我们的KFG餐厅都是非常具有地方特色的。

用马克思主义讲,就是我们的KFG餐厅因地制宜,将KFG餐饮风格与地方特色相结合。

什么是地方特色,就是我们的KFG餐厅根据当地饮食习惯制作出符合当地饮食的料理,店面装修也具有当地的特色。

所以这个时候我们就有了北京小清新风格KFG餐厅,北京豪华风格KFG餐厅,南京小清新风格KFG餐厅,南京豪华风格KFG餐厅。

假如我们用程序代码来表示就是

class NanjingXiaoQingXinKFGStore {
	private KGFFoodLine foodLine = new NanjingFoodLine();
	// ...小清新风格的装饰
}

class NanjingHaoHuaKFGStore {
	private KGFFoodLine foodLine = new NanjingFoodLine();
	// ...豪华风格的装饰
}

class BeijingXiaoQingXinKFGStore {
	private KGFFoodLine foodLine = new BeijingFoodLine();
	// ...小清新风格的装饰
}

class BeijingHaoHuaKFGStore {
	private KGFFoodLine foodLine = new BeijingFoodLine();
	// ...豪华风格的装饰
}

这个时候问题来了,全国至少上千个城市,那么我们的 不同装修风格的 *  地方饮食 将会是一个很庞大的数字,我们是不是真的要写出这么多类来?


这种将风格与特色相互仅仅结合的设计 并不是我们想要的,我们想要的是可以扩展的。

那么怎么扩展呢?

我们只要有一类通用的KFGStore 不管我们是北京小清新风格KFG餐厅,北京豪华风格KFG餐厅,南京小清新风格KFG餐厅,南京豪华风格KFG餐厅。

它们都是KFG餐厅,它们的主要职责都是服务顾客,让顾客在店内有着良好的心情。

至此我们需要抽取店内的共性,然后离散特性。

interface KGFFoodLine {
	public Food cookChip();

	public Food cookHamberger();

	public Food cookChicken();
}

class BeijingFoodLine implements KGFFoodLine {

	@Override
	public Food cookChip() {
		return new Chip("Beijing Chip");
	}

	@Override
	public Food cookHamberger() {
		return new Hamburger("Beijing Hamberger");
	}

	@Override
	public Food cookChicken() {
		return new Chicken("Beijing Chicken");
	}
}

class NanjingFoodLine implements KGFFoodLine {

	@Override
	public Food cookChip() {
		return new Chip("Nanjing Chip");
	}

	@Override
	public Food cookHamberger() {
		return new Hamburger("Nanjing Hamberger");
	}

	@Override
	public Food cookChicken() {
		return new Chicken("Nanjing Chicken");
	}
}

interface Cook {
	public Food cook(FoodType type);
}

abstract class KFGStore implements Cook {
	private KGFFoodLine foodLine;

	public void setFoodLine(KGFFoodLine foodLine) {
		this.foodLine = foodLine;
	}

	@Override
	public Food cook(FoodType type) {
		switch (type) {
		case CHIP:
			return foodLine.cookChip();
		case HAMBURGER:
			return foodLine.cookHamberger();
		case CHICKEN:
			return foodLine.cookChicken();
		default:
			break;
		}
		return null;
	}

	abstract public void decoratePatternDescribe();

}

class QingXinKFGStore extends KFGStore {
	// ...小清新风格的装饰
	@Override
	public void decoratePatternDescribe() {
		// TODO Auto-generated method stub

	}
}

class HaoHuaKFGStore extends KFGStore {
	// ...豪华风格的装饰
	@Override
	public void decoratePatternDescribe() {
		// TODO Auto-generated method stub

	}
}



 解决方案:

桥连模式:将抽象部分与实现部分分离,使它们都可以独立的变化。它是一种结构性模式,又称柄体(Handle and body)模式或者接口(Interface)模式。        当一个抽象可能有多个实现时,通常用继承来协调他们。抽象类的定义对该抽象的接口。而具体的子类则用不同的方式加以实现,但是此方法有时不够灵活。继承机制将抽象部分与他的视线部分固定在一起,使得难以对抽象部分和实现部分独立地进行修改、扩充和充用。

理解桥接模式,重点需要理解如何将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化。



构建模式的组成
抽象类(Abstraction):定义抽象类的接口,维护一个指向Implementor类型对象的指针
扩充抽象类(RefinedAbstraction):扩充由Abstraction定义的接口
实现类接口(Implementor):定义实现类的接口,该接口不一定要与Abstraction的接口完全一致;事实上这两个接口可以完全不同。一般来讲, Implementor接口仅提供基本操作,而 Abstraction则定义了基于这些基本操作的较高层次的操作。
具体实现类(ConcreteImplementor):实现Implementor接口并定义它的具体实现。



按照上述定义,我们寻找该模式的角色对应关系吧。

抽象类:KFGStore,持有一个KFGFoodLine 接口,该接口的具体实现提供不同风格的地方美食。同时定义了一个描述装饰样式的抽象方法,由子类去实现。

扩充抽象类:QingXinKFGStore,HaoHuaKFGStore。对抽象类的方法进行实现,以产生不同装修风格的餐厅。

实现类接口:KFGFoodLine,制作各种美食,提供烹制各种各样美食的基本操作,具体怎么组合,在抽象类中依据顾客的请求合理的调用foodLine.cookxxx()

具体实现:NanjingFoodLine,BeijingFoodLine。按照接口产生独特的美食。


假设 我们 原来有 4种装修 风格, 4 种 美食风格,按照原先的设计方式,那么我们将会得到 4 x 4个类。

但是改进之后 使用Bridge设计模式后, 我们只要 4 + 4个类即可。


我这里需要强调一个问题,那就是使用桥接模式的主要目的并不是减少类,而是将抽象和实现解耦,分离接口及其实现部分,提高可扩充性。


适用性
1). 你不希望在抽象和他的实现部分之间有一个固定的绑定关系,如在程序的运行时刻实现部分应该可以被选择或者切换。
2). 类的抽象以及他的视像都可以通过生成子类的方法加以扩充。这时bridge模式使你可以对不同的抽象接口和实现部分进行组合,并对他们进行扩充。
3). 对一个抽象的实现部分的修改应该对客户不产生影响,即客户的代码不需要重新编译。
4). 你想对客户完全隐藏抽象的实现部分。
5). 你想在多个实现间 共享实现,但同时要求客户并不知道这一点。




这里举spring中ClassPathApplicationContext类作为例子。

我们都知道ClassPathApplicationContext里面有个getBean方法,而这个getBean是BeanFactory接口的实现。

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;

public interface BeanFactory {

	String FACTORY_BEAN_PREFIX = "&";

	Object getBean(String name) throws BeansException;

	<T> T getBean(String name, Class<T> requiredType) throws BeansException;

	<T> T getBean(Class<T> requiredType) throws BeansException;

	Object getBean(String name, Object... args) throws BeansException;

	<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

	boolean containsBean(String name);

	boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

	boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

	boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

	Class<?> getType(String name) throws NoSuchBeanDefinitionException;

	String[] getAliases(String name);

}
而该ClassPathApplicationContext中getBean的实现则是从其父类AbstractApplicationContext实现的。

AbstractApplicationContext:

@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name);
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name, requiredType);
	}

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name, args);
	}

	@Override
	public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType, args);
	}

该父类中的getBeanFactory()实际上是从其父类中继承下来的,对其不可见,只提供了公共接口getBeanFactory()访问

实际上等同于

beanFactory.getBean()


而这里我们的具体BeanFactory实现类则是DefaultListableBeanFactory

ClassPathApplicationContext 并不是唯一的context,还有WebApplicationContext,AnnotationApplicationContext等。

所以我们这里整理一下思路,按照之前的角色划分整理:

抽象类(Abstraction): AbstractApplicationContext

扩充抽象类(RefinedAbstraction):ClassPathApplicationContext,WebApplicationContext,AnnotationApplicationContext
实现类接口(Implementor):BeanFactory。
具体实现类(ConcreteImplementor):DefaultListableBeanFactory




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值