文章目录
一、概念
- 属于行为型设计模式
- 本质抽象封装流程,具体实现。也就是用抽象类将一个固定流程封装起来,具体步骤由不同的子类实现。
- 实现是通过类的继承。
二、生活中应用场景
炒菜:洗锅——>点火——>热锅——>上油——>下原料——>翻炒——>放调料——>出锅
三、角色
抽象模板(AbstractClass):抽象模板列,定义了一套算法框架/流程;
具体实现(ConcreteClass):具体实现类,对算法框架/流程的某些步骤进行了实现。
四、代码实现
以在线课程为例
抽象模板AbstractCourse
public abstract class AbstractCourse {
public final void createCourse(){
//1. 发布预习资料
postPreResource();
//2. 制作课件
createPPT();
//3. 直播授课
liveVideo();
//4. 上传课后资料
postResource();
//5. 布置作业
postHomework();
if(needCheckHomework()){
checkHomework();
}
}
/**
* 检查作业
*/
protected abstract void checkHomework();
//钩子方法
/**
* 判断是否需要检查作业
*/
protected boolean needCheckHomework(){
return true;
}
protected void postHomework(){
System.out.println("布置作业");
}
protected void postResource(){
System.out.println("上传课后资料");
}
protected void liveVideo(){
System.out.println("直播授课");
}
protected void createPPT(){
System.out.println("制作课件");
}
protected void postPreResource(){
System.out.println("发布预习资料");
}
}
具体实现:
Java课程实现类
public class JavaCourse extends AbstractCourse{
private boolean needHomework=false;
public void setNeedHomework(boolean needHomework) {
this.needHomework = needHomework;
}
@Override
protected void checkHomework() {
System.out.println("检查Java作业");
}
@Override
protected boolean needCheckHomework() {
return super.needCheckHomework();
}
}
Python课程实现类:
public class PythonCourse extends AbstractCourse{
@Override
protected void checkHomework() {
System.out.println("检查Python作业");
}
}
客户端测试代码
public class Test {
public static void main(String[] args) {
System.out.println("======架构师课程======");
JavaCourse javaCourse = new JavaCourse();
javaCourse.setNeedHomework(false);
javaCourse.createCourse();
System.out.println("======Python课程======");
PythonCourse pythonCourse = new PythonCourse();
pythonCourse.createCourse();
}
}
五、模版方法模式实现JDBC的操作
1. 创建约束ORM逻辑的接口RowMapper
public interface RowMapper<T> {
/**
* 将 ResultSet 中的行映射为一个对象 T
* @param rs ResultSet 对象
* @param rowNum 行数
* @return 映射后的对象 T
* @throws Exception 抛出异常
*/
T mapRow(ResultSet rs, int rowNum) throws Exception;
}
2.创建封装了所有处理流程的抽象类JdbcTemplate
public class JdbcTemplate {
@SuppressWarnings("all")
private DataSource dataSource;
public JdbcTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
public final List<?> executeQuery(String sql, RowMapper rowMapper, Object... values) {
try {
//1.获取连接
Connection conn=this.getConnection();
//2.创建语句集
PreparedStatement pstm= this.createStatement(conn, sql);
//3.执行语句集
ResultSet rs = this.executeQuery(pstm,values);
//4.处理结果集
List<?> result=this.parseResultSet(rs,rowMapper);
//5.关闭结果集
rs.close();
//6.关闭语句集
pstm.close();
//7.关闭连接
conn.close();
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private List<?> parseResultSet(ResultSet rs, RowMapper rowMapper) throws Exception {
List<Object> result=new ArrayList<>();
int rowNum=0;
while (rs.next()) {
Object obj=rowMapper.mapRow(rs, rowNum++);
result.add(obj);
}
return result;
}
private ResultSet executeQuery(PreparedStatement pstm, Object[] values) throws SQLException {
for (int i = 0; i < values.length; i++) {
pstm.setObject(i , values[i]);
}
return pstm.executeQuery();
}
private PreparedStatement createStatement(Connection conn, String sql) throws SQLException {
return conn.prepareStatement(sql);
}
private Connection getConnection() throws SQLException {
return this.dataSource.getConnection();
}
}
3.创建实体对象Member类
public class Member {
private String username;
private String password;
private String nickname;
private int age;
private String address;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
4.创建数据库操作类MemberDao
public class MemberDao extends JdbcTemplate {
public MemberDao(DataSource dataSource) {
super(dataSource);
}
public List<?> selectAll() {
String sql = "select * from t_member";
return super.executeQuery(sql, new RowMapper<Member>() {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws Exception {
Member member = new Member();
member.setUsername("username");
member.setPassword("password");
member.setAge(rs.getInt("age"));
member.setAddress(rs.getString("address"));
return member;
}
},null);
}
}
5. 客户端测试代码
public class Test {
public static void main(String[] args) {
MemberDao memberDao = new MemberDao(null);
List<?> result=memberDao.selectAll();
System.out.println(result);
}
}
总结
优点
- 将相同处理逻辑封装到抽象父类中,提高代码的复用性
- 不同的代码放到子类中,通过子类扩展增加新的行为,提高代码的扩展性。
缺点
- 类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加,增加了系统实现的复杂度
- 继承关系的自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍。