前言:
视频教程:狂神说Java之通俗易懂的23种设计模式
什么是设计模式?
- 设计模式(Design Pattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。
它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案==> 一种思维,一种态度,一种进步- 1995年,GoF(Gang of Four,四人组/四人帮)合作出版了《设计模式:可复用面向对象软件的基础》一书,共收录了23种设计模式,从此树立了软件设计模式领域的里程碑,人称 【GoF设计模式】
设计模式分类 具体模式 创建型模式:
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。⌛单例模式、⌛工厂模式、⌛抽象工厂模式、⌛建造者模式、⌛原型模式 结构型模式:
这些设计模式关注类和对象的组合。继承的概念被用来组合接口和定义组合对象获得新功能的方式。⌛适配器模式、⌛桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式 行为型模式:
这些设计模式特别关注对象之间的通信。模板方法模、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式
桥接模式
-
桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interfce)模式
-
举个例子:
如果想要用传统的多继承结构实现上述思路,则会造成一个庞大的系统架构:
-
对软件的扩展十分不友好:
如果想要增加一种”掌上平板“,则需增加”掌上平板电脑“,以及各品牌的实现,十分繁琐。
-
同时也破坏了”单一原则“,
单一职责原则**(Single Responsibility Principle, SRP) **:一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。
因为在最后的实现类中,即实现了品牌,又实现了电脑类型,也就是类的拆分不够彻底
-
-
优化分析:
对上述例子可以抽象为两个维度的信息:品牌、电脑类型,如图:
两个维度的交点,便可以理解为一个实体类,同时只要实现品牌和类型两大类便可以造出多种电脑实例。这种对产品实例的维度进行抽象组合的方法便是,桥接模式。
桥接模式:将抽象部分与它的实现部分分离,使他们都可以独立变化【DP】
此处的实现是指抽象类和它派生类用来实现自己的对象【DPE】
实现系统可能有多角度,每一种类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合
代码实例:
对上述例子抽象成桥接模式实现:
两个维度:品牌、电脑:
//品牌接口:
public interface Brand {
void info();
}
//电脑:用组合的方式连接电脑与品牌:
public class Computer {
//搭建电脑与品牌的桥梁
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void info(){
brand.info();//自带的品牌
}
}
具体各自的派生类:
-
品牌:
//苹果牌子 public class Apple implements Brand { @Override public void info() { System.out.print("Apple-"); } }
//联想牌子: public class Lenovo implements Brand { @Override public void info() { System.out.print("联想-"); } }
-
电脑:
public class Desktop extends Computer { public Desktop(Brand brand) { super(brand); } @Override public void info() { super.info(); System.out.println("台式机"); } }
public class Laptop extends Computer { public Laptop(Brand brand) { super(brand); } @Override public void info() { super.info(); System.out.println("笔记本"); } }
-
测试:
public class Test { public static void main(String[] args) { //苹果笔记本 Computer computer = new Laptop(new Apple()); computer.info(); //联想台式机 Computer computer1 = new Desktop(new Lenovo()); computer1.info(); } /* Apple-笔记本 联想-台式机 */ }
此时对两个维度(品牌、电脑)增加种类不会对原有类有过多的修改,只需在对应的维度下增加相应的类即可。
小结:
-
优点:
桥接模式偶尔类似于多继承方案,但是多继承方案违背了类的单一职责原则,复用性比较差,类的个数也非常多。
-
桥接模式是比多继承方案更好的解决方法, 极大的减少了子类的个数,从而降低管理和维护的成本
-
桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。符合开闭原则,就像一座桥,可以把两个变化的维度连接起来。
本文例子是通过在电脑注入品牌,连接两个维度。
-
-
劣势分析:
- 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
- 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
-
桥接模式与适配器模式的对比:
上图对比: GoF23通俗易懂的设计模式之 <适配器模式>
-
个人理解(最简单粗暴):
- 适配器需要中间辅助,桥接则自己动手搭桥
-
意图及主要解决:
- 适配器:(相容)
- **意图:**将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
- **主要解决:**主要解决在软件系统中,常常要将一些"现存的对象"放到新的环境中,而新环境要求的接口是现对象不能满足的。
- 桥接:(分离可扩展)
- **意图:**将抽象部分与实现部分分离,使它们都可以独立的变化。
- **主要解决:**在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
- 适配器:(相容)
-
用法区别
按照GOF的说法,桥接模式和适配器模式用于设计的不同阶段:
桥接模式用于设计的前期,即在设计类时将类规划为逻辑和实现两个大类,是他们可以分别精心演化;
适配器模式用于设计完成之后,当发现设计完成的类无法协同工作时,可以采用适配器模式。然而很多情况下在设计初期就要考虑适配器模式的使用,如涉及到大量第三方应用接口的情况。
-
应用案例:
-
最佳实践:
- 如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
- 抽象化角色和实现化角色可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
- 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需要独立管理这两者。
- 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用
-
具体场景:
-
Java语言通过Java虚拟机实现了平台的无关性.
-
AWT中的Peer架构
-
JDBC驱动程序也是桥接模式的应用之一.
JDBC这里使用桥接模式可以让Driver和Connection下面的类根据不同数据库来实现不同的发展。
其实JDK提供的JDBC数据库访问接口API正是经典的桥接模式的实现者,接口内部可以通过实现接口来扩展针对不同数据库的具体实现来进行扩展,而对外的仅仅只是一个统一的接口调用,调用方过于抽象,可以将其看做每一个JDBC调用程序(这是真实实物,当然不存在抽象)
-
- 最后小唠叨:狂神的设计模式停更了,接下来就要学习黑马的设计模式了:
黑马程序员Java设计模式详解,全网最全23种Java设计模式(图解+框架源码分析+实战)
一起来学习吧