[DP]Bridge设计模式
来源:互联网 发布:java入门到精通pdf 编辑:程序博客网 时间:2024/04/29 15:38
这次我们继续接着我们的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 {@Overridepublic Food cookChip() {return new Chip("Beijing Chip");}@Overridepublic Food cookHamberger() {return new Hamburger("Beijing Hamberger");}@Overridepublic Food cookChicken() {return new Chicken("Beijing Chicken");}}class NanjingFoodLine implements KGFFoodLine {@Overridepublic Food cookChip() {return new Chip("Nanjing Chip");}@Overridepublic Food cookHamberger() {return new Hamburger("Nanjing Hamberger");}@Overridepublic 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;}@Overridepublic 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 {// ...小清新风格的装饰@Overridepublic void decoratePatternDescribe() {// TODO Auto-generated method stub}}class HaoHuaKFGStore extends KFGStore {// ...豪华风格的装饰@Overridepublic 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:
@Overridepublic Object getBean(String name) throws BeansException {assertBeanFactoryActive();return getBeanFactory().getBean(name);}@Overridepublic <T> T getBean(String name, Class<T> requiredType) throws BeansException {assertBeanFactoryActive();return getBeanFactory().getBean(name, requiredType);}@Overridepublic <T> T getBean(Class<T> requiredType) throws BeansException {assertBeanFactoryActive();return getBeanFactory().getBean(requiredType);}@Overridepublic Object getBean(String name, Object... args) throws BeansException {assertBeanFactoryActive();return getBeanFactory().getBean(name, args);}@Overridepublic <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
- [DP]Bridge设计模式
- 设计模式----Bridge模式
- 设计模式:Bridge模式
- 设计模式----Bridge模式
- 设计模式 -- Bridge模式
- 设计模式-Bridge模式
- 【设计模式】bridge模式
- 设计模式----Bridge模式
- 设计模式--------Bridge模式
- 设计模式-Bridge模式
- 设计模式 - Bridge模式
- 设计模式--Bridge 模式
- 设计模式之Bridge
- 设计模式之Bridge
- 设计模式之Bridge
- 设计模式二:bridge
- 设计模式之Bridge
- 设计模式之Bridge
- Redis,Memcache,Mongodb的区别
- Neutron 如何支持多种 network provider - 每天5分钟玩转 OpenStack(70)
- Spring Boot 监听器 过滤器 Servlet 实例
- PAT乙级:1008. 数组元素循环右移问题 (Java)
- HDU 5804 Price List
- [DP]Bridge设计模式
- docker-compose的安装和设定
- Codeforces Round #366 (Div. 2) A. Hulk (简单模拟)
- 领导说我对任务的理解是错的
- Codeforces Round #366 (Div. 2) B. Spider Man (组合游戏)
- 夏令营day4总结
- 《技术人创业攻略》-用技术改变世界!
- PAT乙级:1006. 换个格式输出整数 (Java)
- Codeforces Round #366 (Div. 2) C. Thor(模拟)