Java设计模式之结构型模式(一):桥接模式

一、基本介绍

桥接模式基于类的最小设计原则,通过使用封装,聚合及继承等行为让不同的类承担不同的职责。也就是说,将实现与抽象放在两个不同的类层次中,使两个层次可以独立改变。从而可以保持各部分的独立性以及能够应对它们的功能扩展。

桥接模式的原理UML类图如下:
Java设计模式之结构型模式(一):桥接模式_第1张图片
桥接模式的角色说明:

  • 抽象化角色Abstraction:定义抽象类,并包含一个对实现化对象的引用。
  • 拓展抽象化角色 RefinedAbstraction:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  • 实现化角色Implementor:定义实现化角色的接口,供扩展抽象化角色调用。
  • 具体实现化角色ConcreteImplementorA/B:给出实现化角色接口的具体实现。

二、使用

1.场景

一个咖啡店可以提供大杯(JorumCoffee)、中杯(MediumCoffee)、小杯(SmallCoffee)的咖啡(Coffee),为了满足不同用户的口味,在咖啡中可以添加牛奶(Milk),或者糖(Sugar),或者柠檬(Lemon),提供给用户不同口味的组合,如大杯咖啡加牛奶,中杯咖啡加糖,小杯咖啡加柠檬,小杯咖啡加糖等。冲咖啡的流程:磨咖啡,导入杯中,选择调味品,加入咖啡中,出售。

下面使用桥接模式设计该系统并绘制相应的类图,并用面向对象编程语言实现该模式。

2.UML类图设计

Java设计模式之结构型模式(一):桥接模式_第2张图片
上面的类图各个类代表的角色说明:

  • 抽象化(Abstraction)角色:Coffee类,定义抽象类,并包含一个对实现化对象的引用。
  • 扩展抽象化(Refined Abstraction)角色:SmallCoffee,MediumCoffee,JorumCoffee类,它们是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
  • 实现化(Implementor)角色:Condiment类, 定义实现化角色的接口,供扩展抽象化角色调用。
  • 具体实现化(Concrete Implementor)角色:Milk,Lemon,Sugar类,给出实现化角色接口的具体实现。

3.代码实现

抽象化角色,Coffee类:

public abstract class Coffee {
	protected Condiment Condiment;
	/**
	 * 磨咖啡豆
	 */
	public void grindCoffeeBean() {
		System.out.println("磨咖啡豆");
	}

	/**
	 * 倒咖啡豆到杯中
	 */
	public abstract void putIntoCup();

	/**
	 * 选择调味品
	 */
	public void selectCondiment() {
		// TODO Auto-generated method stub
		System.out.println("选择调味品:【" + this.Condiment.getName() + "】");
	}

	/**
	 * 加入咖啡中
	 */
	public abstract void addToCoffee();

	/**
	 * 出售
	 */
	public void sell() {
		grindCoffeeBean();
		putIntoCup();
		selectCondiment();
		addToCoffee();
		System.out.println("出售");
	}
}

大杯咖啡JorumCoffee类:

public class JorumCoffee extends Coffee {
	public JorumCoffee(Condiment condiment) {
		// TODO Auto-generated constructor stub
		this.Condiment = condiment;
		System.out.println("客户选择的组合套餐是:大杯咖啡+" + condiment.getName());
		System.out.println("开始制作该套餐》》》》》》");
	}
	@Override
	public void putIntoCup() {
		// TODO Auto-generated method stub
		System.out.println("倒入磨好的咖啡豆到大杯中");
	}
	@Override
	public void addToCoffee() {
		// TODO Auto-generated method stub
		System.out.println("将调料加入到大杯咖啡中");
	}
}

中杯咖啡MediumCoffee类:

public class MediumCoffee extends Coffee {
	public MediumCoffee(Condiment condiment) {
		// TODO Auto-generated constructor stub
		this.Condiment = condiment;
		System.out.println("客户选择的组合套餐是:中杯咖啡+" + condiment.getName());
		System.out.println("开始制作该套餐》》》》》》");
	}

	@Override
	public void putIntoCup() {
		// TODO Auto-generated method stub
		System.out.println("倒入磨好的咖啡豆到中杯中");
	}
	@Override
	public void addToCoffee() {
		// TODO Auto-generated method stub
		System.out.println("将调料加入到中杯咖啡中");
	}
}

小杯咖啡 SmallCoffee 类:

public class SmallCoffee extends Coffee {
	public SmallCoffee(Condiment condiment) {
		// TODO Auto-generated constructor stub
		this.Condiment = condiment;
		System.out.println("客户选择的组合套餐是:小杯咖啡+" + condiment.getName());
		System.out.println("开始制作该套餐》》》》》》");
	}
	@Override
	public void putIntoCup() {
		// TODO Auto-generated method stub
		System.out.println("倒入磨好的咖啡豆到小杯中");
	}
	@Override
	public void addToCoffee() {
		// TODO Auto-generated method stub
		System.out.println("将调料加入到小杯咖啡中");
	}
}

抽象类:

public interface Condiment {

	public String getName();
}
public class Lemon implements Condiment {

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return "柠檬";
	}

}
public class Milk implements Condiment {

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return "牛奶";
	}
}
public class Sugar implements Condiment {

	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return "糖";
	}
}

Client客户类进行测试;

public class Client {
	public static void main(String[] args) {
		// 大杯咖啡加牛奶
		Condiment condiment01 = new Milk();
		Coffee coffee01 = new JorumCoffee(condiment01);
		coffee01.sell();
		// 中杯咖啡加糖
		Condiment condiment02 = new Sugar();
		Coffee coffee02 = new MediumCoffee(condiment02);
		coffee02.sell();
		// 小杯咖啡加柠檬
		Condiment condiment03 = new Lemon();
		Coffee coffee03 = new SmallCoffee(condiment03);
		coffee03.sell();
	}
}

程序的运行结果:
Java设计模式之结构型模式(一):桥接模式_第3张图片

三、典型应用

桥接模式在JDBC中的应用,JDBC中的connection接口,要连接不同的数据库需要独自实现该接口,在DriverManager类中提供了重载的获取connection的方法getConnection。connection接口就是实现化角色,针对不同数据库的Connection接口实现类就是具体实现化角色。
Java设计模式之结构型模式(一):桥接模式_第4张图片
与传统的桥接模式不同,DriverManager类没有抽象层父类。上述的类相关的简略UML类图如下:
Java设计模式之结构型模式(一):桥接模式_第5张图片

四、总结

桥接模式实现了抽象和实现部分的分离,从而极大地提高了系统的灵活性,让抽象部分和实现部分独立开,这有助于系统进行分层设计,从而产生更好的结构化系统。
桥接模式替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本
桥接模式的引入增加了系统的理解和设计难度,由于聚合关联关系建立在抽象层,因此其使用范围有一定的局限性。

桥接模式的优点:

  • 分离抽象接口及其实现部分。
  • 桥接模式有时类似于多继承方案,但是多继承方案违背了类的单一职责原则(即一个类只有一个变化的原因),复用性比较差,而且多继承结构中类的个数非常庞大,桥接模式是比多继承方案更好的解决方法。
  • 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
  • 实现细节对客户透明,可以对用户隐藏实现细节。

桥接模式的缺点:

桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。 - 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。

应用场景:
桥接模式通常适用于以下场景。
当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时。
当一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。

参考:
1.http://c.biancheng.net/view/1364.html
2.https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/bridge.html

你可能感兴趣的:(设计模式,设计模式,java,数据库)