文章目录
- 定义
- 策略模式的结构
- QuickStart | Demo
- Step1 | 策略接口
- Step2 | 策略实现
- Step3 | 上下文服务类
- Step4 | 客户端
- 策略模式的特点
- 优点
- 缺点
定义
策略模式Strategy是一种行为模式,它能定义一系列算法,并将每种算法分别放入到独立的类中,以使算法的对象能够相互替换。
比如,你去机场,可以有三种策略:
- 自行车
- 公共汽车
- 出租车
这三种交通方案,自行车不要钱,能欣赏风景;公共汽车便宜速度快;出租车方便速度快,节省时间。这三种方案代表了三种策略,算法。
将上面三种出行方案封装,我们可以灵活选用!
策略模式的结构
通过上图我们知道,策略模式分为四个结构:
- 策略接口【核心】
- 策略实现类
- 上下文Context
- 具体要实现的业务代码,业务逻辑。
- 客户端Client
- 决定使用哪种策略。
QuickStart | Demo
接下来用一个非常容易理解的案例让大家掌握策略模式。
项目结构如下:
├─.idea
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─linghu
│ │ │ └─designer
│ │ │ ├─dao
│ │ │ │ └─impl
│ │ │ └─service
│ │ └─resources
│ └─test
│ └─java
└─target
├─classes
│ └─com
│ └─linghu
│ └─designer
│ ├─dao
│ │ └─impl
│ └─service
└─generated-sources
└─annotations
Step1 | 策略接口
首先定义一个策略接口,这里面封装了数据访问层Dao层的策略方法。
/**
* @author linghu
* @date 2024/7/3 10:27
*/
/*策略接⼝*/
public interface UserDao {
public void insert();
public void update();
public void delete();
public void findById();
}v
Step2 | 策略实现
面向客户,用户,开发者的时候,我们可以选择不同的数据访问方式,我们可以选择:
- JDBC
- JNDI
- ODBC
具体怎么选,我们需要再客户端让用户自己选。那么在这里我们需要定义好这三种策略实现类。
/**
* @author linghu
* @date 2024/7/3 10:28
*/
public class JdbcDao implements UserDao {
@Override
public void insert() {
System.out.println("JDBC⽅式实现数据插⼊");
}
@Override
public void update() {
System.out.println("JDBC⽅式实现数据更新");
}
@Override
public void delete() {
System.out.println("JDBC⽅式实现数据删除");
}
@Override
public void findById() {
System.out.println("JDBC⽅式实现数据查找");
}
}
package com.linghu.designer.dao.impl;
import com.linghu.designer.dao.UserDao;
/**
* @author linghu
* @date 2024/7/3 10:28
*/
public class JndiDao implements UserDao {
@Override
public void insert() {
System.out.println("JndiDao⽅式实现数据插⼊");
}
@Override
public void update() {
System.out.println("JndiDao⽅式实现数据更新");
}
@Override
public void delete() {
System.out.println("JndiDao⽅式实现数据删除");
}
@Override
public void findById() {
System.out.println("JndiDao⽅式实现数据查找");
}
}
package com.linghu.designer.dao.impl;
import com.linghu.designer.dao.UserDao;
/**
* @author linghu
* @date 2024/7/3 10:28
*/
public class JndiDao implements UserDao {
@Override
public void insert() {
System.out.println("JndiDao⽅式实现数据插⼊");
}
@Override
public void update() {
System.out.println("JndiDao⽅式实现数据更新");
}
@Override
public void delete() {
System.out.println("JndiDao⽅式实现数据删除");
}
@Override
public void findById() {
System.out.println("JndiDao⽅式实现数据查找");
}
}
package com.linghu.designer.dao.impl;
import com.linghu.designer.dao.UserDao;
/**
* @author linghu
* @date 2024/7/3 10:28
*/
public class OdbcDao implements UserDao {
@Override
public void insert() {
System.out.println("OdbcDao⽅式实现数据插⼊");
}
@Override
public void update() {
System.out.println("OdbcDao⽅式实现数据更新");
}
@Override
public void delete() {
System.out.println("OdbcDao⽅式实现数据删除");
}
@Override
public void findById() {
System.out.println("OdbcDao⽅式实现数据查找");
}
}
Step3 | 上下文服务类
上下文服务,持有某个策略对象dao,但是策略通过外部传入,服务类本身主要完成业务逻辑 insert()
。
/**
* @author linghu
* @date 2024/7/3 10:33
*/
/*Context*/
public class UserService {
public UserDao dao = null;
public UserService(UserDao dao) {
this.dao = dao;
}
public void createUser(){
System.out.println("正在创建⽤户对象");
dao.insert();
}
}
在这里,我们的策略是通过外部传入的:
public UserService(UserDao dao) {
this.dao = dao;
}
外部策略通过 UserDao dao
传入。
Step4 | 客户端
客户端代码如下:
/**
* @author linghu
* @date ${DATE} ${TIME}
*/
public class Client {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
UserDao dao = null;
switch (input) {
case "jdbc":
dao = new JdbcDao();
break;
case "odbc":
dao = new OdbcDao();
break;
case "jndi":
dao = new JndiDao();
break;
}
//策略的创建者在用户端!
UserService userService = new UserService(dao);
userService.createUser();
}
}
根据文本的不同创建不同的策略:
switch (input) {
case "jdbc":
dao = new JdbcDao();
break;
case "odbc":
dao = new OdbcDao();
break;
case "jndi":
dao = new JndiDao();
break;
}