设计模式分类:(3种类型)
1)结构型类型(7种):站在软件结构的角度思考的,怎么样软件结构扩展性更好。
-1:适配器模式:
-2:桥接模式:
-3:装饰模式:解决类爆炸问题。
-4:组合模式:
-5:外观模式:
-6:享元模式:
-7:代理模式:
一.:结构型—适配器模式(60~65)
1.:基本介绍:(Adapter Pattern)
1)基本介绍:
-1:将某个类的接口,转换成客户端期望的另一个接口表示。
-2:让原本因接口不匹配,不能一起工作的两个类,可以协同工作。
-3:其别名为:包装器(Wrapper)。
2)工作原理:
-1:适配器模式:将一个类的接口,转换成另一种接口,让原本接口不兼容的类,可以兼容。
-2:从用户的角度,看不到被适配者,是解耦了。
-3:用户调用适配器,转化出来的目标接口方法。 适配器再调用被适配者的相关接口方法。
-4:用户收到反馈结果,感觉只是和目标接口交互。如图:
3)适配器模式分类:
-1:类适配器 模式:
-2:对象适配器 模式:
-3:接口适配器 模式:
4)适配器模式 注意事项 & 细节:
-1:三种命名方式(三种分类):是根据 src 是以怎样的形式,给到 Adapter(在 Adapter 里的形式)来命名的。
-2:适配器模式分类:
类适配器 模式:以类给到,在 Adapter 里,就是将 src 当作类,继承实现。
对象适配器 模式:以 对象给到,在 Adapter 里,将 src 作为一个对象,持有。
接口适配器 模式:以接口给到,在 Adapter 里,将 src 作为一个接口,实现。
-3:Adapter 模式:做大的作用还是,将原本不兼容的接口,融合在一起工作。
-4:在实际开发中:实现起来,不拘泥于我们讲解的三种经典形式。
2.:类适配器 模式:
1)类适配器模式 介绍:
Adapter (适配器)类,
通过继承 src(被适配者) 类,
实现 dst(目标) 类接口,
完成 src -> dst 的适配。
1)类适配器模式 注意事项 & 细节:(优缺点)
-1:缺点:Java 是单继承机制:所以 类适配器,需要继承 src(被适配者) 类,这一点算是一个缺点。因为要求 dst(目标) 必须是接口,有一定局限性。
-2:缺点:src(被适配者) 类的方法:在 Adapter 中都会暴露出来,也增加了使用的成本。
-3:优点:由于继承了 src 类:所以它可以根据需求,重写 src 类的方法,使得 Adaper 的灵活性增加了。
2)类适配器模式 应用实例:
-1:应用实例说明:
以生活中,充电器的例子来讲解适配器。
充电器本身相当于 Adapter,220V 交流电相当于 src(被适配者),我的的 dst(目标)是 5v 直流电。
-2:UML 类图分析:
-3:代码实现:
/**
* @author zhangxudong@chunyu.me
* @date 2022/3/5 12:13 下午
*/
public class ClassAdepterClient {
public static void main(String[] args) {
Phone phone = new Phone();
int charging = phone.charging(new VoltageAdaptor());
System.out.println(charging);// 5V
}
}
class Voltage220V {
public int output220V() {
int src = 220;
System.out.println("输出电压 = " + src);
return src;
}
}
interface IVoltage5V {
int output5V();
}
class VoltageAdaptor extends Voltage220V implements IVoltage5V {
@Override
public int output5V() {
int src = super.output220V();
System.out.println("220V -》 5v");
src = 5;
return src;
}
}
class Phone {
public int charging(IVoltage5V iVoltage5V) {
return iVoltage5V.output5V();
}
}
3.:对象适配器 模式:
1)基本介绍:
-1:基本思路,和类的适配器模式相同:只是将 Adapter 类做修改。不是继承 src 类,而是持有 src 类的实例,已解决兼容性的问题。
即:持有 src 类,实现 dst 接口,完成 src -> dst 的适配。
-2:根据“合成复用原则”:在系统中,尽量使用关联关系,来替代继承关系。
-3:对象适配器模式,是适配器模式中常用的一种。
2)使用 对象适配器模型:对 2 的改进:
-1:思路分析:
-2:UML 类图:
-3:代码实现:
/**
* @author zhangxudong@chunyu.me
* @date 2022/3/5 12:13 下午
*/
public class ClassAdepterClient {
public static void main(String[] args) {
VoltageAdaptor voltageAdaptor = new VoltageAdaptor(new Voltage220V());
Phone phone = new Phone();
int charging = phone.charging(voltageAdaptor);
System.out.println(charging);// 5V
}
}
class Voltage220V {
public int output220V() {
int src = 220;
System.out.println("输出电压 = " + src);
return src;
}
}
class VoltageAdaptor implements IVoltage5V {
private Voltage220V voltage220V;
public VoltageAdaptor(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
int src = voltage220V.output220V();
System.out.println("220V -》 5v");
src = 5;
return src;
}
}
interface IVoltage5V {
int output5V();
}
class Phone {
public int charging(IVoltage5V iVoltage5V) {
return iVoltage5V.output5V();
}
}
4.:接口适配器 模式
1)基本介绍:
-1:一些书籍称为:“适配器模式"(Default Adapter Pattern),或 “缺省适配器模式”。
-2:当不需要全部实现接口提供的方法时:
可以先设计一个抽象类实现接口,并为该接口中每个方法,提供一个模式实现(空方法)。
那么该抽象类的子类,可有选择的覆盖父类的某些方法,来实现需求。
-3:适用于一个接口,不想使用其所有的方法的情况。
2)UML 类图:
3)代码实现:
/**
* @author zhangxudong@chunyu.me
* @date 2022/3/5 6:15 下午
*/
public class InterfaceAdepter {
public static void main(String[] args) {
AbstractAdepter abstractAdepter = new AbstractAdepter() {
/**
* 只需重写,我们需要的 m1 方法
*/
@Override
public void m1() {
System.out.println("使用了 m1 的 重写后方法");
}
};
abstractAdepter.m1();
}
}
interface VoltageInterface {
void m1();
void m2();
void m3();
}
abstract class AbstractAdepter implements VoltageInterface {
@Override
public void m1() { // 空实现:}
@Override
public void m2() { // 空实现:}
@Override
public void m3() { // 空实现:}
}
5.:Dispatcher 源码分析:
1)SpringMVC 中,HandlerAdapter(处理器适配器),就使用了 适配器模式:
2)SpringMVC 处理请求的流程回顾:
3)使用 HandlerAdapter 的原因分析:
4)可以看到,处理器的类型不同,有多种实现方式。那么调用方式就不是确定的。如果需要直接调用 controller 方法,需要调用的时候,就得不断的使用 if else 来进行判断,是哪一种子类然后执行。那么,如果后面需要扩展 Controller ,就得修改原来的代码,这样违背了 OCP 原则。
5)动手写一个 SpringMVC 通过适配器设计模式,获取到对应的 Controller 的源码:
-1:Spring 定义了一个适配器接口,使得每一种 Controoler 有一种对应的适配器实现类。
-2:适配器代替 Controller 执行相应的方法。
-3:拓展 Controller 时,只需要增加一个适配器类,就完成了 Spring MVC 的拓展了。这就是设计模式的力量。
-4:代码实现:
public interface Controller {
}
class HttpController implements Controller {
public void doHttpHandler() {
System.out.println("doHttpHandler");
}
}
class SimpleController implements Controller {
public void doSimpleHandler() {
System.out.println("doSimpleHandler");
}
}
class AnnotationController implements Controller {
public void doAnnotationHandler() {
System.out.println("doAnnotationHandler");
}
}
public interface HandlerAdapter {
void handle(Controller handler);
boolean supports(Controller handler);
}
class SimpleHandlerAdapter implements HandlerAdapter {
@Override
public void handle(Controller handler) {
((SimpleController) handler).doSimpleHandler();
}
@Override
public boolean supports(Controller handler) {
return (handler instanceof SimpleController);
}
}
class AnnotationHandlerAdapter implements HandlerAdapter {
@Override
public void handle(Controller handler) {
((AnnotationController) handler).doAnnotationHandler();
}
@Override
public boolean supports(Controller handler) {
return (handler instanceof AnnotationController);
}
}
class HttpHandlerAdapter implements HandlerAdapter {
@Override
public void handle(Controller handler) {
((HttpController) handler).doHttpHandler();
}
@Override
public boolean supports(Controller handler) {
return (handler instanceof HttpController);
}
}
public class DispatcherServlet {
public static List<HandlerAdapter> handlerAdapterList = new ArrayList<>();
public DispatcherServlet() {
handlerAdapterList.add(new AnnotationHandlerAdapter());
handlerAdapterList.add(new HttpHandlerAdapter());
handlerAdapterList.add(new SimpleHandlerAdapter());
}
protected void doDispatch(Controller controller) {
/**
* 此处模拟 SpringMVC ,从 request 取 handler 的对象
* 适配器可以获取到希望的 controller
* HttpController controller = new HttpController();
*/
// 得到对应的适配器
HandlerAdapter handlerAdapter = getHandler(controller);
// 通过适配器,执行对应的 Controller 方法
handlerAdapter.handle(controller);
}
private HandlerAdapter getHandler(Controller controller) {
for (HandlerAdapter handlerAdapter : handlerAdapterList) {
if (handlerAdapter.supports(controller)) {
return handlerAdapter;
}
}
return null;
}
}
二.:结构型—桥接模式模式(66~70)
1.:
1)
2)
3)
4)
5)
6)
2.::
1)问题:
2)
3)
4)
5)
6)
3.:
1)
2)
3)
4)
5)
6)
4.:
1)
2)
3)
4)
5)
6)
5.:
1)
2)
3)
4)
5)
6)
6.:
1)
2)
3)
4)
5)
6)
-1:
-2:
-3:
-4:
-5:
方式一:
方式一:
方式一:
方式一:
三.:结构型—装饰者模式(71~76)
1.:
1)
2)
3)
4)
5)
6)
2.::
1)问题:
2)
3)
4)
5)
6)
3.:
1)
2)
3)
4)
5)
6)
4.:
1)
2)
3)
4)
5)
6)
5.:
1)
2)
3)
4)
5)
6)
6.:
1)
2)
3)
4)
5)
6)
-1:
-2:
-3:
-4:
-5:
方式一:
方式一:
方式一:
方式一:
四.:结构型—组合模式(77~80)
1.:
1)
2)
3)
4)
5)
6)
2.::
1)问题:
2)
3)
4)
5)
6)
3.:
1)
2)
3)
4)
5)
6)
4.:
1)
2)
3)
4)
5)
6)
5.:
1)
2)
3)
4)
5)
6)
6.:
1)
2)
3)
4)
5)
6)
-1:
-2:
-3:
-4:
-5:
方式一:
方式一:
方式一:
方式一:
五.:结构型—外观模式(81~85)
1.:
1)
2)
3)
4)
5)
6)
2.::
1)问题:
2)
3)
4)
5)
6)
3.:
1)
2)
3)
4)
5)
6)
4.:
1)
2)
3)
4)
5)
6)
5.:
1)
2)
3)
4)
5)
6)
6.:
1)
2)
3)
4)
5)
6)
-1:
-2:
-3:
-4:
-5:
方式一:
方式一:
方式一:
方式一:
六.:结构型—享元模式(86~90)
1.:
1)
2)
3)
4)
5)
6)
2.::
1)问题:
2)
3)
4)
5)
6)
3.:
1)
2)
3)
4)
5)
6)
4.:
1)
2)
3)
4)
5)
6)
5.:
1)
2)
3)
4)
5)
6)
6.:
1)
2)
3)
4)
5)
6)
-1:
-2:
-3:
-4:
-5:
方式一:
方式一:
方式一:
方式一:
七.:结构型—代理模式(91~95)
1.:
1)
2)
3)
4)
5)
6)
2.::
1)问题:
2)
3)
4)
5)
6)
3.:
1)
2)
3)
4)
5)
6)
4.:
1)
2)
3)
4)
5)
6)
5.:
1)
2)
3)
4)
5)
6)
6.:
1)
2)
3)
4)
5)
6)
-1:
-2:
-3:
-4:
-5:
方式一:
方式一:
方式一:
方式一: