文章目录
# 前言 适配器 策略模式 责任链 都是设计模式的一种 设计模式的种类很多 多多掌握和理解才能过面试
提示:以下是本篇文章正文内容,下面案例可供参考
一、适配器模式(Adaptor Pattern)
1. 定义
转换一个类的接口为客户端所需要的接口,将两个不兼容的类纠合在一起使用,这个转换的类就是适配器类。它属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份.它的宗旨就是,保留现有类所提供的服务,向客户提供接口,以满足客户的期望。
2. 生活例子(百度)
就是有转换的功能扩容不是重点 更主要的是改变了
中国的电源电压为 220V ,而日本的电源电压 110V ,在国内使用日本原装电器时,就必须有一个电源适配器将 220V 的电压适配至 110V 一般家庭中电源插座有的是两个孔(两项式)的,也有三个孔(三项式)的。很多时候我们可能更多地使用三个引脚的插头,但是那种两孔的插座就不能满足我们的需求,此时我们一般会买一个拖线板,该拖线板的插头是是两脚插头,这样就可以插入原先的两孔插座,同时拖线板上带有很多两孔、三孔的插座!这样不仅可以扩容,更主要的是将两孔的插座转变为三孔的插座
3. 适配器角色
目标(Target)角色:期待得到的接口。
源(Adaptee)角色: 需要适配的接口。
适配器(Adaptor)角色:适配器类是本模式的核心,在Target目标角色与Adaptee源角色之间提供一种过渡。适配器把Adaptee源接口转换成Target目标接口。显然,这一角色不可以是接口,而必须是具体类。
4. 适配器模式分类
类适配器模式:适配器继承源角色类(继承),实现目标接口。()
对象适配器模式:适配器容纳一个它包裹的类的实例(依赖),实现目标接口
区别: 不同之处于两者在包装Adaptee源角色时,前者(类适配)包装的是Adaptee类(因为它同时从Target与Adaptee继承而来,可想而知,类适配的Adatper必须是一个具体类,而Target只能是一个接口),后者(对象适配)则直接包裹了一个源Adaptee的实例。 其实就是吧这个对象放到适配器中的属性。
5. 实例
代码如下(示例)
/**
* @author zhangyifan
* @version 8.0
* @description: 原角色(220v 家庭电源)
* @date 2021/12/4 9:45
*/
public class AdapateeHomePower {
/**
* 提供220v的交流电
* @return
*/
public int supportOutput220v(){
return 220;
}
}
/**
* @author zhangyifan
* @version 8.0
* @description: 用电设备 电子产品充电 目标角色
* @date 2021/12/4 9:47
*/
public interface TargetElectronicProductPower {
/**
* 为各种电子产品充电功能
* @param productType
* 1、为安卓手机
* 2、苹果手机
* 3、平板
* 4、无法适配
*/
void chargePowerDCNV(int productType);
}
/**
* @author zhangyifan
* @version 8.0
* @description:类适配器
* @date 2021/12/4 9:51
*/
public class AdaptorClass extends AdapateeHomePower implements TargetElectronicProductPower{
@Override
public void chargePowerDCNV(int productType) {
//为了拿到源角色/接口 里面的方法 提供220v的交流电
int aC220v = this.supportOutput220v();
//交流转直流
int dC5V=aC220v/44;
if (productType==1){
System.out.println("连接到安卓手机,开始充电,电压为"+dC5V+"电流2A");
}else if(productType==2){
System.out.println("连接到苹果手机,开始充电,电压为"+dC5V+"电流2A");
}else if(productType==3){
System.out.println("连接到平板,开始充电,电压为"+dC5V+"电流2A");
}else{
System.out.println("无法适配");
}
}
}
/**
* @author zhangyifan
* @version 8.0
* @description:对象适配器
* @date 2021/12/4 9:51
*/
public class AdaptorObject implements TargetElectronicProductPower{
//直接声明一个源接口 直接吧源接口定义为属性
private AdapateeHomePower adapateeHomePower=new AdapateeHomePower();
@Override
public void chargePowerDCNV(int productType) {
//为了拿到源角色/接口 里面的方法 提供220v的交流电
int aC220v = adapateeHomePower.supportOutput220v();
//交流转直流
int dC5V=aC220v/44;
if (productType==1){
System.out.println("连接到安卓手机,开始充电,电压为"+dC5V+"电流2A");
}else if(productType==2){
System.out.println("连接到苹果手机,开始充电,电压为"+dC5V+"电流2A");
}else if(productType==3){
System.out.println("连接到平板,开始充电,电压为"+dC5V+"电流2A");
}else{
System.out.println("无法适配");
}
}
}
测试类
/**
* @author zhangyifan
* @version 8.0
* @description:测试类
* @date 2021/12/4 9:57
*/
public class Test {
public static void main(String[] args) {
/* AdaptorClass adaptorClass=new AdaptorClass();
adaptorClass.chargePowerDCNV(2);*/
AdaptorObject adaptorObject=new AdaptorObject();
adaptorObject.chargePowerDCNV(3);
}
}
二、策略模式(Strategy Pattern)
1. 定义
定义了一组算法/业务方法,将每个算法.业务方法都封装起来 并且使他们之间可以互换
2. 现实例子
我们出门的时候会选择不同的出行方式,比如骑自行车、坐公交、坐火车、坐飞机、坐火箭等等,这些出行方式,每一种都是一个策略。 商场现在正在搞活动,有打折的、有满减的、有返利的等等,其实不管商场如何进行促销,说到底都是一些算法,这些算法本身只是一种策略,并且这些算法是随时都可能互相替换的,比如针对同一件商品,今天打八折、明天满100减30,这些策略间是可以互换的
3. 使用场景
- 如果在一个系统里面有许多的类,他们之间的区别仅在于他门的行为,那么使用策略模式可以动态的让一个对象在许多行为中选择一种行为。
- 一个系统动态的在几种算法中选择
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。
- 不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关的数据结构,提高算法的保密性与安全性。
4.实现
代码如下(示例):
/**
* @author zhangyifan
* @version 8.0
* @description: 竞技
* @date 2021/12/4 10:34
*/
public interface GameStrategy {
/**
* 选择英雄
* @param heroName 英雄
* @param skillCombo 技能组合
*/
void heroChoice(String heroName,String skillCombo);
}
策略
/**
* @author zhangyifan
* @version 8.0
* @description: 切换不同策略
* @date 2021/12/4 10:41
*/
public class StrategContext {
private GameStrategy gameStrategy;
/**
* 构造赋值
* @param gameStrategy
*/
public StrategContext(GameStrategy gameStrategy){
this.gameStrategy=gameStrategy;
}
public void executeGameStrategy(String heroName,String skillCombo){
gameStrategy.heroChoice(heroName,skillCombo);
}
}
策略内容
**
* @author zhangyifan
* @version 8.0
* @description:fs
* @date 2021/12/4 10:37
*/
public class MasterHeros implements GameStrategy{
@Override
public void heroChoice(String heroName, String skillCombo) {
System.out.println("我是法师"+heroName+",AP技能"+skillCombo);
}
}
/**
* @author zhangyifan
* @version 8.0
* @description:adc
* @date 2021/12/4 10:38
*/
public class ShooterHeros implements GameStrategy{
@Override
public void heroChoice(String heroName, String skillCombo) {
System.out.println("我是adc"+heroName+",ad伤害,技能"+skillCombo);
}
}
测试
/**
* @author zhangyifan
* @version 8.0
* @description:
* @date 2021/12/4 15:38
*/
public class Test1 {
public static void main(String[] args) {
MasterHeros masterHeros=new MasterHeros();//adc
StrategContext strategContext=new StrategContext(masterHeros);
strategContext.executeGameStrategy("诡术妖姬","wqerw");
System.out.println("--------------------------");
ShooterHeros shooterHeros=new ShooterHeros();
StrategContext strategContext1=new StrategContext(shooterHeros);
shooterHeros.heroChoice("金克斯","AAAAAAAAAAA");
}
}
5、总结
- 优点
策略模式符合“开闭原则”,可以在不修改原有系统的基础什么选择算法和行为,也可以灵活的增加算法和行为
提供了管理修改的算法族的办法
策略模式可以避免使用多重条件转移语句
多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
- 缺点
策略类会过多 ,每一个策略都需要增加一个策略类
所有的策略类方法都需要对外暴露,(就是必须知道策略类才能去现在调用哪一个策略)
三、职责链(Chain of ResponsibilityPattern)
1、定义
责任链是一种设计模式,在责任链模式里,为了避免请求的发送和接收者耦合在一起,于是将所有请求的处理者通过一个对象的引用记住其下家而连接起来形成一条链。并沿着这条链传动该请求,直到一个对象去处理他为止。
2、现实例子
请假流程(员工提交请假申请 班长审批(3天) 主管审批(7天) 主任审批(30天) 副总审批(180天)),采购流程(采购人填写采购单,采购主管审批,总监审批,总经理审批,财务审批,首付款,采购,验货,入库,付尾款),报销流程(填写报销申请,粘贴附件,本部门负责人复核,财务复核,总经理审批,出纳付款)等等。。。
3、实例
请假人载体
代码如下(示例):
/**
* @author zhangyifan
* @version 8.0
* @description: 请假载体
* @date 2021/12/4 16:09
*/
public class LeaveApply {
//请假人姓名
//请假人天数
private String realName;
private int leaveDays;
/**
* 构造方法
* @param realName
* @param leaveDays
*/
public LeaveApply(String realName, int leaveDays) {
this.realName = realName;
this.leaveDays = leaveDays;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public int getLeaveDays() {
return leaveDays;
}
public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
}
}
请假抽象方法
/**
* @author zhangyifan
* @version 8.0
* @description:
* @date 2021/12/4 16:06
*/
public abstract class AbstractLeaveApplyHandler {
//请假级别 不同环节 权限不同
protected final int LEVEL1=3;
protected final int LEVEL2=7;
protected final int LEVEL3=30;
protected final int LEVEL4=180;
//当前处理人的姓名
protected String handlerName;
/**
* 抽象请假处理方法,不同环节子类必须重写方法
* @param leaveApply
*/
protected abstract void handlerLeaveApply(LeaveApply leaveApply);
// 定义下一个环节对象
protected AbstractLeaveApplyHandler nextLeaveApplyHandler;
/**
* 设置下一个,本来可以在子类中编写,如果在子类,每个类都需要这样,所以父类写,子类不写
* @param nextLeaveApplyHandler
*/
public void setNextLeaveApplyHandler(AbstractLeaveApplyHandler nextLeaveApplyHandler){
this.nextLeaveApplyHandler =nextLeaveApplyHandler;
}
}
实施请假角色
/**
* @author zhangyifan
* @version 8.0
* @description: 组长
* @date 2021/12/4 16:17
*/
public class MontiorHander extends AbstractLeaveApplyHandler{
/**
* 给当前处理人姓名赋值
* @param handlerName
*/
public MontiorHander(String handlerName) {
this.handlerName=handlerName;
}
@Override
protected void handlerLeaveApply(LeaveApply leaveApply) {
//请假天数
int leaveDays = leaveApply.getLeaveDays();
//小于3天 组长可以处理
if (leaveDays<=LEVEL1){
System.out.println("组长"+handlerName+"处理了"+leaveApply.getRealName()+"请假申请,通过了");
return;
}
//判断下一个是否处理环节为空为空就不用设置下一级
if (nextLeaveApplyHandler!=null){
nextLeaveApplyHandler.handlerLeaveApply(leaveApply);
}else {
System.out.println("没有下一个处理环节,请假失败");
}
}
}
/**
* @author zhangyifan
* @version 8.0
* @description: 组长
* @date 2021/12/4 16:17
*/
public class ManagerHandler extends AbstractLeaveApplyHandler{
/**
* 给当前处理人姓名赋值
* @param handlerName
*/
public ManagerHandler(String handlerName) {
this.handlerName=handlerName;
}
@Override
protected void handlerLeaveApply(LeaveApply leaveApply) {
//请假天数
int leaveDays = leaveApply.getLeaveDays();
//小于3天 组长可以处理
if (leaveDays>LEVEL1&&leaveDays<=LEVEL2){
System.out.println("主管"+handlerName+"处理了"+leaveApply.getRealName()+"请假申请,通过了");
return;
}
//判断下一个是否处理环节为空为空就不用设置下一级
if (nextLeaveApplyHandler!=null){
nextLeaveApplyHandler.handlerLeaveApply(leaveApply);
}else {
System.out.println("没有下一个处理环节,请假失败");
}
}
}
等等=======
测试
/**
* @author zhangyifan
* @version 8.0
* @description:
* @date 2021/12/4 17:25
*/
public class Test {
public static void main(String[] args) {
ManagerHandler managerHandler=new ManagerHandler("经理3");
DirectorHandler directorHandler=new DirectorHandler("主任2");
MontiorHander montiorHander=new MontiorHander("组长1");
VicePresidentHander vicePresidentHander=new VicePresidentHander("副总");
montiorHander.setNextLeaveApplyHandler(managerHandler);
managerHandler.setNextLeaveApplyHandler(directorHandler);
directorHandler.setNextLeaveApplyHandler(vicePresidentHander);
LeaveApply leaveApply=new LeaveApply("周五",2);
managerHandler.handlerLeaveApply(leaveApply);
}
}
总结
1), 适配器模式 :适配两个不兼容的类一起使用
2), 策略模式 :动态选择多种功能和算法使用方便客户使用
3), 责任链模式 :帮助完成流程类的功能模式 避免使用多重条件转移语句