设计模式全文
适配器模式
- 不同国家的电源插座不同,通过多功能转接插头进行转换
- Adapter Pattern,包装器
Wrapper
,结构型模式
,将某个类的接口,转成客户端期望的另一个接口的表示,主要目的是兼容性
,让原本因接口不匹配不能一起工作的两个类可以协同工作
A类方法由于
参数或者返回值类型不匹配
,不能直接调用B类方法,通过转接器进行调用
- 主要分三类,
类适配器模式
、对象适配器模式
、接口适配器模式
- 工作原理
- 将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容
- 从用户的角度看不到
被适配者
,是解耦的- 用户调用适配器转换而来的目标接口方法,适配器再调用被适配者的相关接口方法
- 用户的反馈,只是与目标接口交互
类适配器
- 通过继承
src类被适配者
,实现dst类接口
,完成适配 - 案例,220V电压要转换成5V电压,给手机充电
- 被适配类
public class Voltage220V {
public int output220V() {
int src = 220;
System.out.println("Voltage220V");
return src;
}
}
- 适配接口
public interface IVoltage5V {
public int output5V();
}
- 类适配器,继承220V,实现转换成5V
public class VoltageAdapter extends Voltage220V implements IVoltage5V{
@Override
public int output5V() {
int src = output220V();
int dest = src / 40;
return dest;
}
}
- 手机使用,只使用5V的电压
public class Phone {
public void charging(IVoltage5V i) {
if (i.output5V() == 5) {
System.out.println("charging");
} else if (i.output5V() > 5) {
System.out.println("i.output5V() > 5");
}
}
}
- 缺点,类适配器需要继承被适配类,从被适配类作为起点,进行转换
对象适配器
- 持有
src被适配者的对象实例
- 通过聚合绑定被适配类
public class ObjectVoltageAdapter implements IVoltage5V{
private Voltage220V voltage220V;
//通过构造器传入
public ObjectVoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
int dest = 0;
if (null != voltage220V) {
int src = voltage220V.output220V();
System.out.println("ObjectVoltageAdapter");
dest = src / 40;
}
return dest;
}
}
接口适配器
- 缺省适配器模式,适用于一个接口不想使用其所有方法
- 当不需要全部实现接口提供的方法时,设计一个抽象类实现接口,并为该接口中每个方法提供一个默认实现
空方法
- 案例结构
- InterfaceVoltageAdapter
public class InterfaceVoltageAdapter extends VoltagePhone{
private Voltage220V voltage220V;
//通过构造器传入
public InterfaceVoltageAdapter(Voltage220V voltage220V) {
this.voltage220V = voltage220V;
}
@Override
public int output5V() {
int dest = 0;
if (null != voltage220V) {
int src = voltage220V.output220V();
System.out.println("InterfaceVoltageAdapter");
dest = src / 40;
}
return dest;
}
}
- Phone,依赖于
IVoltagePhone
接口
public class Phone {
public void charging(IVoltagePhone i) {
if (i.output5V() == 5) {
System.out.println("charging");
} else if (i.output5V() > 5) {
System.out.println("i.output5V() > 5");
}
}
}
- 使用
Phone phone = new Phone();
phone.charging(new InterfaceVoltageAdapter(new Voltage220V()));
SprintMVC框架源码
DispatcherServlet
中的doDispatch方法
,根据请求拿到映射的handler,就是一个控制器;通过handler,获取一个适配器,不同的handler需要不同的适配器处理
- 先拿到request
- 得到
Handler
(controller)- 得到对应的
Adapter
getHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
//遍历所有的handlers
Iterator var2 = this.handlerAdapters.iterator();
while(var2.hasNext()) {
HandlerAdapter adapter = (HandlerAdapter)var2.next();
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
HandlerAdapter
public interface HandlerAdapter {
boolean supports(Object var1);
@Nullable
ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
long getLastModified(HttpServletRequest var1, Object var2);
}
HandlerAdapter
下的具体实现适配器- 拿到
适配器
后,适配器调用方法,返回ModelAndView
- 类图关系
- 当
扩展controller类型
的时候,只需要增加一个适配器
即可完成扩展,类似手机根据不同的电压输入,产生不同的处理方式
桥接模式
- 案例,对不同手机类型、不同品牌实现相同的操作
- Bridge,结构型设计模式,将实现和抽象放在两个不同的类的层次,两个层次可以独立改变
- 基于类的最小设计原则,修改代码时,尽量少增加几个类,将抽象和具体分离开来,保持各部分的独立性,和功能扩展
- 抽象类,维护了Implementor及它的实现类
- ReFinedAbstraction,抽象类的子类
- Implementor,行为实现类的接口,桥接类,将实现和抽象连接,抽象类通过
Implementor
,调用具体的方法- 抽象类和接口是聚合的关系,是调用和被调用的关系
- 类图,将手机类型和品牌类型分类,通过
手机抽象类
和品牌接口
进行桥接 - 品牌接口,手机功能
public interface Brand {
void call();
void close();
void open();
}
- 品牌实现
public class Vivo implements Brand{
@Override
public void call() {
System.out.println("Vivo Call");
}
@Override
public void close() {
System.out.println("Vivo close");
}
@Override
public void open() {
System.out.println("Vivo open");
}
}
- 抽象类,将品牌传入手机
public abstract class Phone {
private Brand brand;
public Phone(Brand brand) {
this.brand = brand;
}
protected void open() {
this.brand.open();
}
protected void close() {
this.brand.close();
}
protected void call() {
this.brand.call();
}
}
- 抽象的实现类,折叠手机
public class FoldedPhone extends Phone{
public FoldedPhone(Brand brand) {
super(brand);
}
@Override
protected void open() {
super.open();
System.out.println("FoldedPhone open");
}
@Override
protected void close() {
super.close();
System.out.println("FoldedPhone close");
}
@Override
protected void call() {
super.call();
System.out.println("FoldedPhone call");
}
}
JDBC源码
mysql
包中的Driver
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
//注册驱动,拿到连接
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
registerDriver
public static synchronized void registerDriver(java.sql.Driver driver)
throws SQLException {
registerDriver(driver, null);
}
Connection
的实现类,DriverManager
通过getConncetion
获取连接- 类图,
Connection
类似品牌,不同的品牌和数据库,有不同的连接;DriverManager
注册不同的驱动,类似使用不同的手机和品牌,获取不同的连接
小结
- 将抽象和实现分离,增加灵活性,助于系统分层
- 对于系统的高层部分,只需要知道抽象部分和实现部分的接口,其他由具体的业务类实现
- 桥接模式替代了多层继承方案,减少子类的个数
- 要求有两个独立变化的维度,适用于
不希望使用继承或因为多层级继承导致系统类的个数急剧增加的系统
- JDBC驱动程序
- 银行转账系统,转账分类
网上、柜台、ATM
;转账用户普通、银卡、金卡
- 消息管理,消息类型
即使消息、延时消息
;消息分类手机、邮箱、QQ