定义
桥梁模式也叫做桥接模式。将抽象和实现解耦,使得两者可以独立地变化。
#彻底的解耦并没有什么意义。实现指的是抽象类和派生类用来实现自己的对象。
通用类图
#抽象角色引用实现角色,或者说抽象角色的部分实现是由实现角色完成的。
1)Abstraction-抽象化角色
它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类。
2)Implementor-实现化角色
它是接口或者抽象类,定义角色必需的行为和属性。
3)RefinedAbstraction
它引用实现化角色对抽象化角色进行修正。
4)ConcreteImplementor
它实现接口或抽象类定义的方法和属性。
通用案例
/**
* 场景类
*/
public class Client1 {
public static void main(String[] args) {
//定义一个实现化角色
Implementor implementor = new ConcreteImplementor1();
//定义一个抽象化角色
Abstraction abstraction = new RefinedAbstraction(implementor);
//执行
abstraction.request();
}
}
/**
* 实现化角色
*/
interface Implementor{
//基本方法
void doSomething();
void doAnything();
}
/**
* 具体实现化角色
*/
class ConcreteImplementor1 implements Implementor{
@Override
public void doSomething() {
//业务逻辑处理
System.out.println("ConcreteImplementor1-doSomething()");
}
@Override
public void doAnything() {
//业务逻辑处理
System.out.println("ConcreteImplementor1-doAnything()");
}
}
/**
* 具体实现化角色
*/
class ConcreteImplementor2 implements Implementor{
@Override
public void doSomething() {
//业务逻辑处理
System.out.println("ConcreteImplementor2-doSomething()");
}
@Override
public void doAnything() {
//业务逻辑处理
System.out.println("ConcreteImplementor2-doAnything()");
}
}
/**
* 抽象化角色
*/
abstract class Abstraction{
//定义对实现化角色的引用
private Implementor imp;
//约束子类必须实现该构造函数
public Abstraction(Implementor imp) {
this.imp = imp;
}
//自身的行为和属性
public void request(){
this.imp.doSomething();
}
//获得实现化角色
public Implementor getImp() {
return imp;
}
}
/**
* 具体抽象化角色
*/
class RefinedAbstraction extends Abstraction{
//覆写构造函数
public RefinedAbstraction(Implementor imp) {
super(imp);
}
//修正父类的行为
@Override
public void request() {
/**
* 业务处理....
*/
super.request();
super.getImp().doAnything();
}
}
业务案例
案例1
/**
* 场景类
*/
public class Client2 {
public static void main(String[] args) {
HouseCorp houseCorp = new HouseCorp();
houseCorp.makeMoney();
ClothesCorp clothesCorp = new ClothesCorp();
clothesCorp.makeMoney();
}
}
/**
* 抽象公司
*/
abstract class Corp{
abstract void produce();
abstract void sell();
public void makeMoney(){
this.produce();
this.sell();
}
}
/**
* 房地产公司
*/
class HouseCorp extends Corp{
@Override
void produce() {
System.out.println("HouseCorp-produce()");
}
@Override
void sell() {
System.out.println("HouseCorp-sell()");
}
@Override
public void makeMoney() {
super.makeMoney();
}
}
/**
* 服装公司
*/
class ClothesCorp extends Corp{
@Override
void produce() {
System.out.println("ClothesCorp-produce()");
}
@Override
void sell() {
System.out.println("ClothesCorp-sell()");
}
@Override
public void makeMoney() {
super.makeMoney();
}
}
--
HouseCorp-produce()
HouseCorp-sell()
ClothesCorp-produce()
ClothesCorp-sell()
案例2
/**
* 场景类
*/
public class Client3 {
public static void main(String[] args) {
HouseCorp houseCorp = new HouseCorp(new House());
houseCorp.makeMoney();
ShanZhaiCorp shanZhaiCorp = new ShanZhaiCorp(new IPod());
shanZhaiCorp.makeMoney();
}
}
/**
* 抽象产品类
*/
abstract class Product{
abstract void beProducted();
abstract void beSelled();
}
/**
* 房子
*/
class House extends Product{
@Override
void beProducted() {
System.out.println("House-beProducted()");
}
@Override
void beSelled() {
System.out.println("House-beSelled()");
}
}
/**
* IPod
*/
class IPod extends Product{
@Override
void beProducted() {
System.out.println("IPod-beProducted()");
}
@Override
void beSelled() {
System.out.println("IPod-beSelled()");
}
}
/**
* 抽象公司类
*/
abstract class Corp{
//定义一个抽象产品对象,不知道具体是什么产品
private Product product;
//构造函数,由子类定义传递具体的产品进来
public Corp(Product product) {
this.product = product;
}
public void makeMoney(){
//生产
this.product.beProducted();
//销售
this.product.beSelled();
}
}
/**
* 房地产公司
*/
class HouseCorp extends Corp{
public HouseCorp(House house) {
super(house);
}
@Override
public void makeMoney() {
super.makeMoney();
}
}
/**
* 山寨公司
*/
class ShanZhaiCorp extends Corp{
public ShanZhaiCorp(Product product) {
super(product);
}
@Override
public void makeMoney() {
super.makeMoney();
}
}
--
House-beProducted()
House-beSelled()
IPod-beProducted()
IPod-beSelled()
优点
1)抽象和实现抽离。
2)优秀的扩充能力。
3)实现细节对客户透明。
使用场景
#并不是一涉及继承就要考虑使用桥梁模式。桥梁模式的意图还是对变化的封装,尽量把可能变化的因素封装到最细、最小的逻辑单元中,避免风险扩散。
1)不希望或不适用使用继承的场景
例如继承层次过渡、无法更细化设计颗粒等场景,需要考虑使用桥梁模式。
继承是,一定要在是”is-a”的关系时再考虑使用,而不是任何时候都去使用。
2)接口或抽象类不稳定的场景
明知道接口不稳定还想通过实现或继承来实现业务需求,那是得不偿失的,也是比较失败的做法。
3)重用性要求较高的场景
设计的颗粒度越细,则被重用的可能性就越大,而采用继承则受父类的限制,不可能出现太细的颗粒度。
4)桥梁模式描述了类间弱关联关系。对于比较明确不发生变化的,则通过继承来完成;若不能确定是否会发生变化的,那就认为是会发生变化,则通过桥梁模式来解决。
合成/聚合复用原则
定义
合成/聚合复用原则(CARP),尽量/优先使用合成/聚合,尽量不要使用类继承。
通用类图
1)合成和聚合都是关联的特殊种类。聚合表示一种弱的”拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的”拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
2)优先使用对象的合成/聚合有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。
#学会用对象的职责(下述例子中的手机品牌或功能),而不是对象的结构来考虑问题!
而不是
标题:设计模式(二十二)结构型模式(对象结构型模式)桥接模式-BRIDGE
作者:yazong
地址:https://blog.llyweb.com/articles/2020/12/14/1607876476250.html