模板方法模式(Template Method Pattern)
- 介绍:模板模式通常又叫模板方法模式(Template Method Pattern)是指定义一个算法的骨架,并允许子类为一个或者 多个步骤提供实现
模板方法使得子类可以在不改变算法结构的情况下,重新定义 算法的某些步骤。
属于行为性设计模式
- 使用场景
- 一次性实现一个算法的不变的部分,并将可变的行为留给 子类来实现。
- 各子类中公共的行为被提取出来并集中到一个公共的父类 中,从而避免代码重复。
- 优点:
- 提高代码的复用性。
- 提高代码的扩展性。
- 符合开闭原则。
- 缺点:
- 类数目的增加。
- 间接地增加了系统实现的复杂度
- 继承关系自身缺点,如果父类添加新的抽象方法,所有子 类都要改一遍
//mvn依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
// 以jdbc 的数据库连接为例
/**
* ORM映射定制化的接口
*/
public interface RowMapper<T> {
T mapRow(ResultSet rs,int rowNum) throws Exception;
}
//模板
public abstract class JdbcTemplate {
private DataSource dataSource;
public JdbcTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
public List<?> executeQuery(String sql, RowMapper<?> rowMapper, Object[] values){
//TODO 以下方法子类集成使用的 ,若不允许子类修改,可以添加fianl关键字
try {
//1、获取连接
Connection conn = this.getConnection();
//2、创建语句集
PreparedStatement pstm = this.createPrepareStatement(conn,sql);
//3、执行语句集
ResultSet rs = this.executeQuery(pstm,values);
//4、处理结果集
List<?> result = this.paresResultSet(rs,rowMapper);
//5、关闭结果集
this.closeResultSet(rs);
//6、关闭语句集
this.closeStatement(pstm);
//7、关闭连接
this.closeConnection(conn);
return result;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
protected void closeConnection(Connection conn) throws Exception {
//数据库连接池,我们不是关闭
conn.close();
}
protected void closeStatement(PreparedStatement pstm) throws Exception {
pstm.close();
}
protected void closeResultSet(ResultSet rs) throws Exception {
rs.close();
}
protected List<?> paresResultSet(ResultSet rs, RowMapper<?> rowMapper) throws Exception {
List<Object> result = new ArrayList<Object>();
int rowNum = 1;
while (rs.next()){
result.add(rowMapper.mapRow(rs,rowNum ++));
}
return result;
}
protected ResultSet executeQuery(PreparedStatement pstm, Object[] values) throws Exception {
for (int i = 0; i < values.length; i++) {
pstm.setObject(i,values[i]);
}
return pstm.executeQuery();
}
protected PreparedStatement createPrepareStatement(Connection conn, String sql) throws Exception {
return conn.prepareStatement(sql);
}
public Connection getConnection() throws Exception {
return this.dataSource.getConnection();
}
}
//entity
public class User {
private String uid;
private String username;
private int age;
private String addr;
// setget()
}
//Dao
public class UserDao extends JdbcTemplate {
public UserDao(DataSource dataSource) {
super(dataSource);
}
public List<?> selectAll(){
String sql = "select * from t_user";
return super.executeQuery(sql, new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws Exception {
User member = new User();
//字段过多,可使用原型模式
member.setUid(rs.getString("uid"));
member.setUsername(rs.getString("username"));
member.setAge(rs.getInt("age"));
member.setAddr(rs.getString("addr"));
return member;
}
},null);
}
}
适配器模式(Adapter Pattern)
- 介绍:适配器模式(Adapter Pattern)是指将一个类的接口转换成 客户期望的另一个接口,使原本的接口不兼容的类可以一起工作
属于结构型设计模式。
- 使用场景
- 已经存在的类,它的方法和需求不匹配(方法结果相同或相似) 的情况。
- 适配器模式不是软件设计阶段考虑的设计模式,是随着软件维护, 由于不同产品、不同厂家造成功能类似而接口不相同情况下的解决 方案
- 优点:
- 能提高类的透明性和复用,现有的类复用但不需要改变。
- 目标类和适配器类解耦,提高程序的扩展性。
- 在很多业务场景中符合开闭原则。
- 缺点:
- 适配器编写过程需要全面考虑,可能会增加系统的复杂性
- 增加代码阅读难度,降低代码可读性,过多使用适配器会使系统 代码变得凌乱
//以用户登录为例, 账号密码登录,qq登录,微信登录等 (策略 、工厂、适配器)
//entity
public class User {
private String username;
private String password;
private String mid;
private String info;
//setget() ...
}
//result Entity
public class ResultMsg {
private int code;
private String msg;
private Object data;
//setget() ...
}
//adapter
/**
* 在适配器里面,这个接口是可有可无,不要跟模板模式混淆
* 模板模式一定是抽象类,而这里仅仅只是一个接口
* Created by Tom on 2019/3/16.
*/
public interface LoginAdapter {
boolean support(Object adapter);
ResultMsg login(String id,Object adapter);
}
//qq 登录
public class LoginForQQAdapter implements LoginAdapter {
public boolean support(Object adapter) {
return adapter instanceof LoginForQQAdapter;
}
public ResultMsg login(String id, Object adapter) {
return ew ResultMsg(200,"登录成功",id + ": 恭喜登录成功");;
}
}
// 微信登录
public class LoginForWechatAdapter implements LoginAdapter {
public boolean support(Object adapter) {
return adapter instanceof LoginForWechatAdapter;
}
public ResultMsg login(String id, Object adapter) {
return null;
}
}
//其他登录方式 token、微博等等
......
// 登录方法
public class SiginService {
/**
* 注册方法
* @param username
* @param password
* @return
*/
public ResultMsg regist(String username,String password){
return new ResultMsg(200,"注册成功",new Member());
}
/**
* 登录的方法
* @param username
* @param password
* @return
*/
public ResultMsg login(String username,String password){
return new ResultMsg(200,"登录成功",username + ": 恭喜登录成功");
}
}
/**
* 只扩展
*/
public interface IPassportForThird {
/**
* QQ登录
* @param id
* @return
*/
ResultMsg loginForQQ(String id);
/**
* 微信登录
* @param id
* @return
*/
ResultMsg loginForWechat(String id);
/**
* 记住登录状态后自动登录
* @param token
* @return
*/
ResultMsg loginForToken(String token);
/**
* 手机号登录
* @param telphone
* @param code
* @return
*/
ResultMsg loginForTelphone(String telphone, String code);
/**
* 注册后自动登录
* @param username
* @param passport
* @return
*/
ResultMsg loginForRegist(String username, String passport);
}
//结合策略模式、工厂模式、适配器模式
public class PassportForThirdAdapter extends SiginService implements IPassportForThird {
public ResultMsg loginForQQ(String id) {
// return processLogin(id,RegistForQQAdapter.class);
return processLogin(id,LoginForQQAdapter.class);
}
public ResultMsg loginForWechat(String id) {
return processLogin(id,LoginForWechatAdapter.class);
}
public ResultMsg loginForToken(String token) {
return processLogin(token,LoginForTokenAdapter.class);
}
public ResultMsg loginForTelphone(String telphone, String code) {
return processLogin(telphone,LoginForTelAdapter.class);
}
public ResultMsg loginForRegist(String username, String passport) {
super.regist(username,passport);
return super.login(username,passport);
}
private ResultMsg processLogin(String key,Class<? extends LoginAdapter> clazz){
try{
//适配器不一定要实现接口
LoginAdapter adapter = clazz.newInstance();
//判断传过来的适配器是否能处理指定的逻辑
if(adapter.support(adapter)){
return adapter.login(key,adapter);
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
// 客户端调用
public static void main(String[] args) {
IPassportForThird passportForThird = new PassportForThirdAdapter();
passportForThird.loginForQQ("");
}