- 关于设计模式的总结有结合网上优质的文章以及本人在实际工作当中使用到的场景概述。
- 会总结关于工作当中我们做为开发者常用到的几种设计模式。
- 由于工作原因,关于博文的总结都是在工作之余完成的,有不好的地方欢迎指正,谢谢。
- 所有关于设计模式的代码,都会托管到:设计模式代码,欢迎关注。
时空链接:
在日常工作开发中我们为什么要使用到设计模式呢?本人做为一名JAVA开发人员,最先想到的是"万物皆对象",不服咱就new一个呗。但是为了开发人员之间的通信,为了可以更准确地描述及问题的解决方案,又不得不考虑到设计模式。好处呢?当然是提高代码的复用性、扩展性和减少代码冗余的问题了。可以使同开发者更好的阅读和理解代码逻辑。
设计模式六大原则
- 开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了程序的扩展性好,易于维护和升级。
- 里氏代换原则(Liskov Substitution Principle)
(来自百度百科)里氏代换原则(Liskov Substitution Principle)面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对"开-闭"原则的补充。实现"开-闭"原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现。所以里氏代换原则是对实现抽象化的具体步骤的规范。
- 依赖倒转原则(Dependence Lnversion Principle)
这个是开闭原则的基础。具体内容:针对接口编程,依赖于抽象而不依赖于具体。(也就是说,接口或抽象类不依赖于实现类,实现类依赖于接口或者抽象类。更精简的定义就是:面向接口编程(Object-Oriented Design,OOD))。
- 接口隔离原则(Interface Segregation Principle)
使用多个隔离的接口,比使用单个接口好。还是一个降低类之间耦合度为基准。都是为了服务"降低依赖,降低耦合"。
- 迪米特法则(Demeter Principle)
(来自百度百科)迪米特法则又叫做最少知识原则(Least Knowledge Principle 简写LKP),一个实体应当尽量少的与其它实体之间发生相互作用,使得系统功能模块相对独立。也就是说一个类对于其他类知道的越少越好,一个对象应对其他对象有尽可能少的了解,只和朋友通信,不和陌生人说话。
- 合成复用原则(Composite Reuse Principle)
合成复用原则是尽量使用合成/聚合的方式,而不是使用继承(表示在软件复用时,要尽量先使用组合或聚合等关联关系来实现,其次才考虑使用继承关系来实现)。
设计模式分类
设计模式总体来说分为三大类
- 创建型模式:原型模式、单例模式、工厂方法模式、抽象工厂模式、建造者模式共五种。
- 结构型模式:适配器模式、装饰模式、代理模式、外观模式、桥接模式、组合模式、享元模式共七种。
- 行为模式:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式共十一种。
下面开始我们的策略模式吧
策略模式
- 什么是策略模式?
- 其实策略模式就是对算法的包装,是把算法的责任和算法本身分割开来,委派给不同的对象管理,最终实现解决多重if判断问题。举个例子,比如我们平时出行旅行吧,可能每个人对于选择的交通出行方式各不相同,有骑自行车、有坐火车、有坐高铁,也有乘坐飞机的。虽然出行方式各不相同,但做的事情都大致相同-去旅行。
- 上面的场景也可以这样描述:如果在一个系统中有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为(也就是上面所说解决了多重if判断问题)。
- 使用场景
- 相信很多开发者或多或少都接触过erp系统开发,在进行流程审核时,可以选择不同的类型来达到最终的审核结果。比如有工作汇报、KPI/OKR、微创新等审核流程。
- 说说我们平时的聚合支付吧,有支付宝支付、小米支付、京东支付和微信支付等等,大大小小的平台,这时作为开发者的我们要对接那么多的平台,要写那么多的if else if ,想想就难受,还是使用策略模式来解决该问题吧。
public String audit(String type){
if(type.equals("工作汇报")) {
//TODO
return "工作汇报流程审核处理";
}
if(type.equals("KPI/OKR")) {
//TODO
return "KPI/OKR流程审核处理";
}
if(type.equals("微创新")) {
//TODO
return "微创新流程审核处理";
}
return "未找到审核处理流程";
}
来自网络图对策略模式的图解:
- 策略模式环境搭建
创建项目,名称为:springboot_design_pattern
- maven环境依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- 配置文件显示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.5.RELEASE</version>
</plugin>
</plugins>
</pluginManagement>
</build>
定义一个抽象角色
package com.lee.strategy.service;
/**
* @author zfl_a
* @date 2020/8/10
* @project springboot_design_pattern
*/
public abstract class AuditService {
/**
* 抽象,子类具体实现
* @param name
* @param msg
* @return
*/
public abstract boolean operation(String name,String msg);
/**
* 公用方法
* @param typeName
*/
protected void updateAuditInfo(String typeName){
System.out.println("更新了"+typeName+"审核信息");
}
}
具体实现-微创新实现类
package com.lee.strategy.service.impl;
import com.lee.strategy.service.AuditService;
import org.springframework.stereotype.Service;
/**
* @author zfl_a
* @date 2020/8/10
* @project springboot_design_pattern
*/
@Service
public class InnovateAuditServiceImpl extends AuditService {
@Override
public boolean operation(String name, String msg) {
//TODO
System.out.println(name+"操作了微创新审核流程,留言内容:"+msg);
//调用父类
super.updateAuditInfo("微创新");
return true;
}
}
具体实现-KPI/OKR实现类
package com.lee.strategy.service.impl;
import com.lee.strategy.service.AuditService;
import org.springframework.stereotype.Service;
/**
* @author zfl_a
* @date 2020/8/10
* @project springboot_design_pattern
*/
@Service
public class KPIAuditServiceImpl extends AuditService {
@Override
public boolean operation(String name, String msg) {
//TODO
System.out.println(name+"操作了KPI/OKR审核流程,留言内容:"+msg);
//调用父类
super.updateAuditInfo("KPI/OKR");
return true;
}
}
具体实现-工作汇报实现类
package com.lee.strategy.service.impl;
import com.lee.strategy.service.AuditService;
import org.springframework.stereotype.Service;
/**
* @author zfl_a
* @date 2020/8/10
* @project springboot_design_pattern
*/
@Service
public class WorkReportAuditServiceImpl extends AuditService {
@Override
public boolean operation(String name, String msg) {
//TODO
System.out.println(name+"操作了工作汇报审核流程,留言内容:"+msg);
//调用父类
super.updateAuditInfo("工作汇报");
return true;
}
}
定义一个枚举类,封装三个实现类对应的信息,相当于上下文。(可在数据库中实现)
package com.lee.strategy.enumeration;
/**
* @author zfl_a
* @Desc 定义了枚举类实现,也可以定义在数据库中,根据类型取值
* @date 2020/8/10
* @project springboot_design_pattern
*/
public enum AuditEnum {
INNOVATE_ADUIT("2","innovateAuditServiceImpl"),
KPI_AUDIT("3","KPIAuditServiceImpl"),
WORK_REPORT_AUDIT("4","workReportAuditServiceImpl");
private String type;
private String impl;
private AuditEnum(String type,String impl){
this.type = type;
this.impl = impl;
}
public static String getImpl(String type){
for(AuditEnum auditEnum : AuditEnum.values()) {
if(type.equals(auditEnum.getType())) {
return auditEnum.getImpl();
}
}
return null ;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getImpl() {
return impl;
}
public void setImpl(String impl) {
this.impl = impl;
}
}
定义一个具体业务接口
package com.lee.strategy.service;
/**
* @author zfl_a
* @date 2020/8/10
* @project springboot_design_pattern
*/
public interface StrategyService {
boolean audit(String name,String msg,String type);
}
定义一个具体业务接口实现类
package com.lee.strategy.service.impl;
import com.lee.strategy.enumeration.AuditEnum;
import com.lee.strategy.service.AuditService;
import com.lee.strategy.service.StrategyService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author zfl_a
* @date 2020/8/10
* @project springboot_design_pattern
*/
@Service
public class StrategyServiceImpl implements StrategyService {
//自动装配AuditService的所有实现类,以全类名首字母小写作为key
@Autowired
private Map<String, AuditService> auditMap ;
@Override
public boolean audit(String name, String msg, String type) {
if(StringUtils.isBlank(type)) {
return false ;
}
//根据不同类型审核
String auditType = AuditEnum.getImpl(type);
if(StringUtils.isNotBlank(auditType)) {
AuditService auditService = auditMap.get(auditType);
auditService.operation(name,msg);
}
return true;
}
}
定义一个策略Controller
package com.lee.strategy.controller;
import com.lee.strategy.service.StrategyService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* @author zfl_a
* @date 2020/8/10
* @project springboot_design_pattern
*/
@RestController
@RequestMapping("/strategy")
public class StrategyController {
@Autowired
private StrategyService strategyService ;
/**
* 审核流程 返回值不建议Map,可定义成响应结果对象封装
* @param name 审核人
* @param msg 留言内容
* @param type 类型 2微创新 3KPI/OKR 4工作汇报,在实际工作当中根据实际业务
* @return
*/
@PostMapping("/audit")
public Map<String,Object> audit(String name,String msg ,String type) {
Map<String,Object> results = new HashMap<>();
results.put("code","200");
results.put("msg","审核成功");
if(StringUtils.isBlank(type)) {
results.put("code","-1");
results.put("msg","请传递审核类型");
return results ;
}
boolean audit = strategyService.audit(name, msg, type);
if(!audit) {
results.put("code","-2");
results.put("msg","审核失败");
}
return results ;
}
}
访问,如下图所示:
最终结果:
所有关于设计模式的代码,都会托管到:设计模式代码,欢迎关注。希望和大家一起共同成长!