首先 ,我们来复现问题。然后再去根据问题 解决问题。
场景:
我们现在有个消息站,需要去推送消息,消息的类型有:普通消息。
消息发送方法有:短信发送。
新建发送消息接口:
/**
* 发送消息接口
* @author Biao
*
*/
public interface Message {
/**
* 发送消息
* @param message 要发送的消息内容
* @param to 消息的接收者
*/
void send(String message,String to);
}
发送普通短信消息的类
/**
* 短信模式短消息
*
* @author Biao
*
*/
public class CommonMessageSMS implements Message {
@Override
public void send(String message, String to) {
System.out.println("发送普通短信短消息:" + message + ",给" + to);
}
}
现在需求变更:需要添加一个加急的短信消息
我们先做加急消息的接口
/**
* 加急消息的抽象接口
*
* @author Biao
*
*/
public interface UrgencyMessage extends Message {
/**
* 监控消息的处理(区分普通消息)
*
* @param messageId
* 消息编号
*/
void watch(String messageId);
}
加急短信消息类
/**
* 加急短信消息
*
* @author Biao
*
*/
public class UrgencyMessageSMS implements UrgencyMessage {
@Override
public void watch(String messageId) {
// 加急处理方法
}
@Override
public void send(String message, String to) {
System.out.println("发送加急短信消息:" + message + ",给" + to);
}
}
需求再次变更:需要添加 加急邮箱消息和普通邮箱消息
这时我们需要添加2个类 一个普通邮箱消息类 一个加急邮箱消息类 如果需求再次变更 需要添加一个特急消息。 特急消息需要有短信、邮箱 、微信消息 并且 普通消息 加急消息都要添加 。
我们的类图现在是这样:
上面就画了两种消息。还有一种也是一样这个时候我们项目拥有12个类 以后每添加一种消息类型 比如 微博消息 这时候我们需要多添加3个类,如果我们在添加一个超特急消息呢。是不是要死人了哈哈~ 这个时候就要用到我们的桥接模式了。
桥接模式定义:
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
使用场景
在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就要使用Bridge模式。
模板代码
我们先看桥接模式的模板代码
抽象部分-Abstraction:
//持有实现部分的引用
private Implementor implementor;
public Abstraction(Implementor implementor) {
this.implementor = implementor;
}
/**
* 通过调用实现部分具体的方法实现具体的功能
*/
public void operation(){
implementor.operationImpl();
}
再来两个具体的实现
public class ConcreteImplementorA implements Implementor{
@Override
public void operationImpl() {
//具体的实现
}
}
public class ConcreteImplementorB implements Implementor{
@Override
public void operationImpl() {
//具体的实现
}
}
实现部分:
public interface Implementor {
/**
* 实现抽象部分的具体方法
*/
void operationImpl();
}
具体的扩展
public class RefinedAbstraction extends Abstraction{
public RefinedAbstraction(Implementor implementor) {
super(implementor);
}
public void refinedOperation(){
//对Abstraction 中的方法扩展
}
}
具体使用
好了 到这里大家差不多明白了吧,那么我们来拿上面的案例来具体使用下这个设计模式:
先来一个抽象的消息-AbstractMessage:
public abstract class AbstractMessage {
//持有发送消息方式的引用(实现部分的引用)
protected MessageImplementor implementor;
public AbstractMessage(MessageImplementor implementor) {
super();
this.implementor = implementor;
}
/**
* 发送消息
* @param message
* @param to
*/
public void sendMessage(String message,String to){
implementor.send(message, to);
}
}
消息的实现:
public interface MessageImplementor {
/**
* 发送消息
* @param message
* @param to
*/
void send(String message,String to);
}
有了消息 我们来个消息的实现吧:
public class CommonMessage extends AbstractMessage {
public CommonMessage(MessageImplementor implementor) {
super(implementor);
}
}
发送一个邮件消息:
public class MessageEmail implements MessageImplementor {
@Override
public void send(String message, String to) {
System.out.println("发送邮件消息:"+message+",给"+to);
}
}
发送一个手机消息:
public class MessageMobile implements MessageImplementor {
@Override
public void send(String message, String to) {
System.out.println("发送手机消息:"+message+",给"+to);
}
}
来个特急消息的类型:
public class SpecialUrgencyMessage extends AbstractMessage {
public SpecialUrgencyMessage(MessageImplementor implementor) {
super(implementor);
}
public void hurry(){
}
}
来个加急消息的类型:
public class UrgencyMessage extends AbstractMessage {
public UrgencyMessage(MessageImplementor implementor) {
super(implementor);
}
/**
* 监控
* @param messageId
*/
public void watch(String messageId){
}
}
案例很简单。但是实际使用可能会有点复杂。
桥接模式的定义是:
将抽象部分与它的实现部分分离,使它们都可以独立地变化。
那么 那个可以定义为抽象部分那个部分可以定义为实现部分呢。
根据上面的案例 发送消息的类型可能会不断的增加。而且增加的频率可能会高。那么消息类型 可能增加缓慢。那么我就把增加缓慢的定义为抽象的。
简单来说:主动地定义为实现的,被动的定义为抽象的
我们再来一个案例来实践下吧!
我们去喝咖啡,咖啡有大杯的有小杯的。有加糖的。有不加糖的,有加奶的,有不加奶的。那么我们来分析这个那部分是抽象的那部分是实现的呢?
先看案例:
先来抽象咖啡类,持有添加什么类型的引用
public abstract class Coffee {
// 持有实现部分的引用
protected CoffeeAdditives impl;
public Coffee(CoffeeAdditives impl) {
super();
this.impl = impl;
}
/**
* 咖啡具体做成了什么样子由子类决定
*/
public abstract void makeCoffee();
}
咖啡需要添加的东西:
public abstract class CoffeeAdditives {
/**
* 添加方法
* @return
*/
public abstract String add();
}
先来大杯咖啡:
public class LargeCoffee extends Coffee{
public LargeCoffee(CoffeeAdditives impl) {
super(impl);
}
@Override
public void makeCoffee() {
System.out.println("大杯的"+impl.add()+"咖啡");
}
}
加的东西:
public class Milk extends CoffeeAdditives {
@Override
public String add() {
return "加奶";
}
}
小杯咖啡:
public class SmallCoffee extends Coffee{
public SmallCoffee(CoffeeAdditives impl) {
super(impl);
}
@Override
public void makeCoffee() {
System.out.println("小杯的"+impl.add()+"咖啡");
}
}
好了 这个设计模式很简单。具体使用还需要多练习!