一、引言
马上要国庆了哎,从1949年10月1号新中国成立,到今年是新中国成立第70周年,祝祖国早日实现百年计划 ~~~
小编在这里赌还有小伙伴并不知道中国的两个百年计划是什么,不清楚赶紧点击下方链接科普一下。
https://zhidao.baidu.com/question/524909909660576405.html
咦,国庆你去哪儿玩?
是在跟我说玩吗? 需求开发完了吗?该做的工作做完了吗?学习完了吗?
就算就算没做完,小编依旧要玩哈哈哈哈,但是为了不妨碍中国广大人民群众给祖国庆生,小编决定在家附近玩~~~
在家学习学习,运动运动,看看电影,吃吃饭,学学做菜,溜溜猫猫狗狗,快乐似神仙~
打算出去游玩的小伙伴,千万千万千万要注意人身财产安全哟。(小编在家看着你们堵车和排队,哈哈哈哈哈哈)
二、传统解决方式
言归正传,我们先来看一个案例,手机现在是我们的日常必需品之一,别跟小编说你不用手机 ~~
近几年全面屏、刘海屏等多种款式的手机,很多不同的品牌厂商也纷纷开始制作。
需求:那么现在,要求对不同手机款式的不同品牌实现操作编程(比如开机、关机、打电话之类的操作)。
最容易想到的设计方式如下图,可能小伙伴也有其他想法,
1、先定义一个手机包括哪些属性、功能等基本抽象类。
2、由不同的款式来实现或者继承手机抽象类
3、最后是由不同的厂商来制造具体的手机,提供操作。
那么这种方案有什么弊端呢?
问题一:扩展性问题,如果再等几年又出来一个其他款式的手机(折叠屏),就需要增加各个品牌手机的折叠屏类,同样如果我们增加一个手机品牌,也要在不同的手机款式下新增,就很容易导致类爆炸(类的数量太多)。
问题二:违反了单一指责原则,当我们增加手机款式时,要同时增加所有品牌的手机,这样增加了代码维护成本。
三、桥接模式解决方式
现我们就来根据桥接模式来改善传统方式的设计。
基本介绍
桥接模式(Bridge)是一种结构型设计模式,将实现与抽象放在两个不同的层次中,使两个层次可以独立改变。桥接模式基于类的最小设计原则,通过使用封装、聚合、继承等行为让不同的类承担不同的职责。它的主要特定就是把抽象与实现分离开来,从而可以保持个部分的独立性以及对应他们的功能扩展。
桥接模式关系图
1、可以看出桥接模式分为两大类,一个是款式,一个是品牌。 品牌是手机具体实现,而款式是抽象,两者进行了分离
2、在手机款式中,聚合品牌这个类,充当一个桥接的作用
3、在这种设计架构上,最小程度的减少类来实现功能,即使新增款式、或者品牌,只需要增加对应的一个类即可。
具体代码实现
步骤一: 创建一个品牌接口,定义打电话的方法,需要具体品牌来实现。
/**
* @Auther: IT贱男
* @Date: 2019/8/16 11:31
* @Description: 桥接模式 - 品牌接口
*/
public interface Brand {
void call();
}
步骤二:创建具体的品牌,以小米为例,来实现打电话的功能。
/**
* @Auther: IT贱男
* @Date: 2019/8/16 11:33
* @Description: 小米手机
*/
public class XiaoMi implements Brand {
@Override
public void call() {
System.out.println("小米手机打电话");
}
}
步骤三:创建手机款式抽象类,通过聚合的方式把具体实现和抽象结合在一起,充当桥接的作用。
/**
* @Auther: IT贱男
* @Date: 2019/8/16 11:38
* @Description: 手机款式抽象类
*/
public abstract class Phone {
// 聚合品牌接口
private Brand brand;
// 通过构造函数传入具体手机品牌
public Phone(Brand brand) {
this.brand = brand;
}
/**
* 调用手机品牌的打电话方法
*/
public void call() {
brand.call();
}
}
步骤四:创建具体手机款式,继承手机款式抽象类,通过构造方法来接收具体品牌。
/**
* @Auther: IT贱男
* @Date: 2019/9/25 15:44
* @Description: 全面屏款式手机
*/
public class FullScreenPhone extends Phone {
public FullScreenPhone(Brand brand) {
super(brand);
}
public void call() {
System.out.print("这是全面屏");
super.call();
}
}
步骤五:测试测试,通过传入手机品牌,来创建一个具体款式手机,从而调用打电话的方法。
/**
* @Auther: IT贱男
* @Date: 2019/8/16 11:42
* @Description:
*/
public class Client {
public static void main(String[] args) {
// 通过传入具体手机品牌,创建一个具体款式手机
Phone phone = new FullScreenPhone(new XiaoMi());
phone.call();
}
}
这是全面屏小米手机打电话
Process finished with exit code 0
扩展新的手机或者款式
扩展一:扩展一个刘海屏幕款式,只需要新增一个类即可通用所有品牌手机。
/**
* @Auther: IT贱男
* @Date: 2019/9/25 16:19
* @Description: 刘海屏手机
*/
public class BangsScreenPhone extends Phone {
public BangsScreenPhone(Brand brand) {
super(brand);
}
public void call(){
System.out.print( "这是刘海屏");
super.call();
}
}
/**
* @Auther: IT贱男
* @Date: 2019/8/16 11:42
* @Description:
*/
public class Client {
public static void main(String[] args) {
// 通过传入具体手机品牌,创建一个具体手机款式
Phone phone = new BangsScreenPhone(new XiaoMi());
phone.call();
}
}
扩展二:扩展一个新的华为品牌手机,同样新增一个手机品牌,通用全部的手机款式。
/**
* @Auther: IT贱男
* @Date: 2019/9/25 16:20
* @Description: 华为品牌
*/
public class HuaWei implements Brand {
@Override
public void call() {
System.out.println("华为手机打电话");
}
}
/**
* @Auther: IT贱男
* @Date: 2019/8/16 11:42
* @Description:
*/
public class Client {
public static void main(String[] args) {
// 通过传入具体手机品牌,创建一个具体手机款式
Phone phone = new BangsScreenPhone(new HuaWei());
phone.call();
}
}
四、桥接模式的注意和细节
1、实现了抽象和实现部分的分离,极大的提高了系统的灵活性,让抽象和实现部分独立开来,有助于系统进行分层设计,从而产生更好的结构化系统。
2、桥接模式替代多层继承方案,可以减少子类的个数,降低系统的管理和维护成本。
3、增加了系统的理解和设计难度,要求开发者针对抽象进行设计和编程。
4、使用桥接模式需要注意应用场景,别为了设计模式而去使用设计模式,而是根据实际情况而定。