目录
桥梁模式【Bridge Pattern】,什么是桥梁模式?核心思想?优缺点?主要角色?桥梁模式实现?
什么是桥梁模式?
桥梁模式(Bridge Pattern)是一种结构型设计模式,它的目的是将抽象部分与实现部分分离,使它们能够独立地变化。通过这种方式,系统可以在不改变客户端代码的情况下,更容易地扩展和维护。
桥梁模式核心思想
桥梁模式将对象的抽象和实现解耦,二者可以独立地进行扩展和变化。抽象部分不再直接与实现部分绑定,而是通过一个桥接(Bridge)接口与实现部分进行关联。这样,我们可以改变抽象的同时改变实现,而不需要修改二者的代码。
桥梁模式优缺点
优点
(1)分离抽象和实现
实现了抽象与实现的解耦,使得它们可以独立地扩展。
(2)提高系统的可扩展性
可以分别扩展抽象层次和实现层次,互不影响。
(3)符合开闭原则
在不修改已有代码的情况下,可以增加新的抽象类和实现类。
(4)减少子类的数量
通过桥接模式,可以减少因多维度变化而导致的子类爆炸问题。
缺点
(1)增加系统的复杂性
引入了额外的抽象层次,可能会增加系统的复杂性。
(2)需要充分理解设计问题
如果使用不当,可能导致系统设计过于复杂,不利于维护。
桥梁模式主要角色
(1)抽象(Abstraction)
定义了高层次的操作,依赖于实现接口(Implementor)。抽象类中通常包含一个指向实现部分的引用,抽象类并不会具体实现行为,而是通过该引用委托给实现类。
(2)扩展抽象(Refined Abstraction)
继承自抽象类,提供更具体的实现或进一步扩展抽象功能。
(3)实现接口(Implementor)
为实现部分定义接口,通常包含一些基础操作,这些操作将被具体的实现类实现。抽象部分通过实现接口来与具体实现交互。
(4)具体实现类(Concrete Implementor)
实现实现接口中的操作,这些是实际执行的功能。
桥梁模式的应用场景?
桥梁模式的适用场景主要集中在需要将抽象和实现解耦的场景,尤其是系统的抽象和实现部分可能会随着时间变化的情况。
(1)当系统需要在抽象和实现之间添加更多的灵活性时
如果一个类存在多个维度的变化,将抽象与实现分离可以让两者独立扩展。例如,假设你有一个图形类,它可以绘制不同类型的形状(如圆形和正方形),而且它们可以使用不同的颜色进行绘制。在这种情况下,你可以通过桥梁模式将“形状”和“颜色”两个维度分离。
(2)当不希望在抽象类中直接实现功能时
桥梁模式将实现部分独立出来,通过接口的方式进行关联,从而实现抽象类与实现类的解耦,提升了灵活性。
(3)当系统需要在不同的硬件或操作系统平台之间进行切换时
桥梁模式可以用于跨平台的应用程序开发,不同的实现类可以适应不同的平台或设备,而抽象部分保持不变。
桥梁模式实现
梦想中的自己,身价过亿,有两个大公司,一个是房地产公司,一个是服装制造业,这两个公司都很赚钱,天天帮我在累加财富,其实是什么公司倒是不关心,我关心的是是不是在赚钱,赚了多少,这才是我关心的,我是商人呀,唯利是图是我的本性,偷税漏税是我的方法,欺上瞒下、压榨员工血汗
我是的手段嘛。
类图很简单,声明了一个 Corp 抽象类,定义一个公司的抽象模型,公司首要是赚钱的,不赚钱谁开公司,做义务或善举那也是有背后利益支撑的,我还是赞成这句话“天下熙熙,皆为利来;天下壤壤,皆为利往”。
1、定义一个产品的抽象模型
package com.uhhe.common.design.bridge.implementor;
/**
* 整个集团公司的产品类
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:44
*/
public abstract class Product {
/**
* 甭管是什么产品它总要是能被生产出来
*/
public abstract void produce();
/**
* 生产出来的东西,一定要销售出去,否则扩本呀
*/
public abstract void sell();
}
2、具体的产品(衣服、房子】山寨机iPod)
(1)衣服
package com.uhhe.common.design.bridge.implementor;
/**
* 集团公司生产的衣服
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:50
*/
public class Clothes extends Product {
@Override
public void produce() {
System.out.println("生产出的衣服是这个样子的...");
}
@Override
public void sell() {
System.out.println("生产出的衣服卖出去了...");
}
}
(2)房子
package com.uhhe.common.design.bridge.implementor;
/**
* 集团公司盖的房子
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:49
*/
public class House extends Product {
/**
* 豆腐渣就豆腐渣呗,好歹也是个房子
*/
@Override
public void produce() {
System.out.println("生产出的房子是这个样子的...");
}
/**
* 虽然是豆腐渣,也是能够销售出去的
*/
@Override
public void sell() {
System.out.println("生产出的房子卖出去了...");
}
}
(3)山寨机iPod
package com.uhhe.common.design.bridge.implementor;
/**
* 生产iPod了
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:51
*/
public class IPod extends Product {
@Override
public void produce() {
System.out.println("生产出的iPod是这个样子的...");
}
@Override
public void sell() {
System.out.println("生产出的iPod卖出去了...");
}
}
4、定义一个公司的抽象模型
package com.uhhe.common.design.bridge.abstraction;
import com.uhhe.common.design.bridge.implementor.Product;
/**
* 定义一个公司的抽象模型,公司首要是赚钱的,不赚钱谁开公司,做义务或善举那也是有背后利益支撑的
* 天下熙熙,皆为利来;天下壤壤,皆为利往
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:37
*/
public abstract class Corp {
/**
* 定义一个产品对象,抽象的了,不知道具体是什么产品
*/
private final Product product;
/**
* 构造函数,由子类定义传递具体的产品进来
*
* @param product 产品
*/
public Corp(Product product) {
this.product = product;
}
/**
* 公司是干什么的?赚钱的呀,不赚钱傻子才干
*/
public void makeMoney() {
// 每个公司都是一样,先生产
this.product.produce();
// 然后销售
this.product.sell();
}
}
4、具体的公司(服装、房地产、山寨公司)
(1)服装公司
package com.uhhe.common.design.bridge.abstraction;
import com.uhhe.common.design.bridge.implementor.Clothes;
/**
* 服装公司,这个行当现在不怎么样
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:41
*/
public class ClothesCorp extends Corp {
/**
* 构造函数,由子类定义传递具体的产品进来
*
* @param clothes 衣服
*/
public ClothesCorp(Clothes clothes) {
super(clothes);
}
@Override
public void makeMoney(){
super.makeMoney();
System.out.println("服装公司赚大钱了...");
}
}
(2)房地产公司
package com.uhhe.common.design.bridge.abstraction;
import com.uhhe.common.design.bridge.implementor.House;
/**
* 房地产公司,按照翻译来说应该叫realty corp,这个是比较准确的翻译
* * 但是我问你房地产公司翻译成英文,你第一反应什么?对嘛还是house corp!
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:39
*/
public class HouseCorp extends Corp {
/**
* 定义传递一个House产品进来
*
* @param house 产品
*/
public HouseCorp(House house) {
super(house);
}
@Override
public void makeMoney(){
super.makeMoney();
System.out.println("房地产公司赚大钱了...");
}
}
(3)山寨公司
package com.uhhe.common.design.bridge.abstraction;
import com.uhhe.common.design.bridge.implementor.Product;
/**
* 山寨公司
* 我是山寨老大,你流行啥我就生产啥
*
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:54
*/
public class ShanZhaiCorp extends Corp {
/**
* 产什么产品,不知道,等被调用的才知道
*
* @param product 产品
*/
public ShanZhaiCorp(Product product) {
super(product);
}
/**
* 狂赚钱
*/
@Override
public void makeMoney() {
super.makeMoney();
System.out.println("我赚钱呀...");
}
}
5、使用桥梁模式
package com.uhhe.common.design.bridge;
import com.uhhe.common.design.bridge.abstraction.HouseCorp;
import com.uhhe.common.design.bridge.abstraction.ShanZhaiCorp;
import com.uhhe.common.design.bridge.implementor.Clothes;
import com.uhhe.common.design.bridge.implementor.House;
import com.uhhe.common.design.bridge.implementor.IPod;
/**
* @author nizhihao
* @version 1.0.0
* @date 2023/2/28 13:42
*/
public class Client {
/**
* 桥梁模式【Bridge Pattern】
* 桥梁模式的优点就是类间解耦,两个角色都可以自己的扩展下去,不会相互影响,这个也符合 OCP 原则。
* <p>
* <p>
* <p>
* 桥梁模式的几个概念熟悉一下,大家有没有注意到我把Corp类以及它的两个实现类放到了Abstraction包中,
* 把House以及相关的三个实现类放到了 Implementor 包中
* 这两个包分别对应了桥梁模式的 业务抽象角色(Abstraction)和 业务实现角色(Implementor)
* <p>
* <p>
* 现在只有房地产公司和山寨公司,那以后我会不会增加一些其他的公司呢?
* 或者房地产公司会不会对业务进行细化,比如:分为公寓房公司、别墅公司、以及商业房公司等等呢?
* 那我告诉你,会的,绝对的会的,但是你发觉没,这种变化对我们上面的类图没有大的修改,充其量是扩展,
* 你看呀:
* ①增加公司,你要么继承 Corp 类,要么继承 HouseCorp 或 ShanZhaiCorp,不用再修改原有的类了;
* ②增加产品,继承 Product 类,或者继承 House 类,你要把房子分为公寓房、别墅、商业用房等等;
* 你现在都是在扩展,唯一你要修改的就是 Client 类,你类都增加了哪能不修改调用呢,也就是说 Corp 类和
* Product 类都可以自由的扩展,而不会对整个应用产生太的变更,这就是桥梁模式。
* <p>
* 对类的继承有什么看法吗?
* 继承的优点有很多,可以把公共的方法或属性抽取,父类封装共性,子类实现特性,这是继承的基本功能
* <p>
* 缺点有没有?
* 有,强关联关系,父类有个方法,子类也必须有这个方法,是不可选择的,那这会带来扩展性的问题
* <p>
* 举个简单的例子来说明这个问题:
* Father 类有一个方法 A,Son 继承了这个方法,然后 GrandSon 也继承了这个方法,问题是突然有一天 Son
* 要重写父类的这个方法,他敢做吗?绝对不敢!GrandSon 可是要用从 Father 继承过来的方法 A,你修改了,
* 那就要修改 Son 和 GrandSon 之间的关系,那这个风险就大了去。
* <p>
* 桥梁模式就是这一问题的解决方法,桥梁模式描述了类间弱关联关系,还说上面的那个例子,
* Father 类完全可以把可能会变化的方法放出去,Son 子类要有这个方法很简答,桥梁搭过去,获得这个方法,
* GrandSon 也一样,即使你 Son 子类不想使用这个方法了,也没关系,对 GrandSon 不产生影响,他不是从你 Son 中继承来的方法。
* <p>
* 对于比较明确不发生变化的,则通过继承来完成,若不能确定是否会发生变化的,那就认为是会发生变化,则通过桥梁模式来解决
*/
public static void main(String[] args) {
House house = new House();
System.out.println("-------房地产公司是这个样子运行的-------");
// 先找到我的公司
HouseCorp houseCorp = new HouseCorp(house);
// 看我怎么挣钱
houseCorp.makeMoney();
System.out.println("\n");
System.out.println("-------山寨公司是这样运行的-------");
ShanZhaiCorp shanZhaiCorp = new ShanZhaiCorp(new Clothes());
shanZhaiCorp.makeMoney();
System.out.println("\n");
System.out.println("-------山寨公司是这样运行的-------");
ShanZhaiCorp shanZhaiCorp1 = new ShanZhaiCorp(new IPod());
shanZhaiCorp1.makeMoney();
}
}