百万架构师第六课:设计模式:策略模式及模板模式

2025/1/4 6:03:20

本文主要是介绍百万架构师第六课:设计模式:策略模式及模板模式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

策略模式

举例:

  • 比较器
  • 旅行路线
  • 固定算法策略(封装)
  • 买东西结算支付

场景:

根据用户的需求处理数据时候需要对算法做出选择,固定的一些算法(不再发生变化的算法),扩展。(算法会变的时候,不建议用策略模式)

​ 客户本身就知道要采用什么样的算法去计算。(有选择的权利)

assets/支付的策略模式.png

支付的策略模式

策略模式代码:

Order.class
public class Order {
    private String uId;
    private String orderId;
    private double amount;

    public Order(String uId, String orderId, double amount) {
        this.uId = uId;
        this.orderId = orderId;
        this.amount = amount;
    }

//    public PayState pay(Payment payment) {
//        return payment.pay(this.uId,this.amount);
//    }

    // 这个参数,完全可以用 Payment 这个接口来代替
    // 为什么?

    // 完美地解决了 switch 的过程, 不需要在代码逻辑中写 switch le
    // 更不需要写 if else 了
    public PayState pay(PayType payType) {
        return payType.getPayment().pay(this.uId, this.amount);
    }
}
PayState.class
/**
 * 支付完成以后的状态
 **/
public class PayState {
    private int code;
    private String msg;
    private Object data;

    public PayState(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    @Override
    public String toString() {
        return "PayState{" +
                "[交易状态:]code=" + code +
                ", [交易详情:]data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }
}
Payment.class
public interface Payment {
    // 每次增加一个支付渠道,我们就要去维护这个接口一次
//    public final static Payment ALI_PAY = new AliPay();
//    public final static Payment JD_PAY = new JDPay();
//    public final static Payment WECHAT_PAY = new WeChatPay();
//    public final static Payment UNION_PAY = new UnionPay();

    PayState pay(String uid, double amount);
}
AliPay.class
public class AliPay implements Payment {
    
    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用支付宝");
        System.out.println("查询余额,开始扣款");
        return new PayState(200,"支付成功",amount);
    }
}
JDPay.class
public class JDPay implements Payment {

    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用京东白条支付");
        System.out.println("查询余额,开始扣款");
        return new PayState(200,"支付成功",amount);
    }
}
UnionPay.class
public class UnionPay implements Payment {

    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用银联卡支付");
        System.out.println("查询余额,开始扣款");
        return new PayState(200,"支付成功",amount);
    }
}
WeChatPay.class
public class WeChatPay implements Payment {

    public PayState pay(String uid, double amount) {
        System.out.println("欢迎使用微信支付");
        System.out.println("直接从微信红包扣款");
        return new PayState(200,"支付成功",amount);
    }
}
PayType enum
public enum PayType {
    ALI_PAY(new AliPay()),
    JD_PAY(new JDPay()),
    WECHAT_PAY(new WeChatPay()),
    UNION_PAY(new UnionPay());

    private Payment payment;

    PayType(Payment payment) {
        this.payment = payment;
    }

    public Payment getPayment() {
        return payment;
    }
}
PayStrategyTest.class
public class PayStrategyTest {
    public static void main(String[] args) {
        // 省略把商品添加到购物车,再从购物车下单
        // 直接从订单开始
        Order order = new Order("1", "20180311001000009", 324.11);

        // 开始支付,选择  微信支付、支付宝、银联卡、京东白条、财付通
        // 每个渠道它支付的具体的算法是不一样的
        // 基本的算法是固定的
//        PayState payState = order.pay(new AliPay());
//        PayState payState = order.pay(new JDPay());
        // 这个值是在支付的时候才决定用哪个值
        PayState payState = order.pay(PayType.ALI_PAY);
        System.out.println(payState);
    }
}
ComparableTest.class
public class ComparableTest {
    public static void main(String[] args) {
        // 这就是一个策略模式
        new ArrayList<Object>().sort(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        });
    }
}
assets/Payment策略模式设计的支付的类图.png

Payment策略模式设计的支付的类图

设计模式都是混合使用,都没有单一存在的。

用设计模式,是用来解决复杂问题的,把复杂的问题简单化。不要去生搬硬套:容易把简单的事情复杂化。

把简单的事情搞复杂,谁都会,但是把复杂的事情变简单,那需要技术含量(借鉴经验)

​ 一个类,直接 new 一下就好了,为什么要搞个工厂模式呢?

Spring 中的策略模式

  • BeanFactory

  • ListableFactory

  • …Factory

    根据用户的配置去选择用什么样的工厂创建出来,这就是策略模式,通常会跟抽象工厂模式结合使用

举例:爬虫程序

  • 根据 URL 来自动选择
    • BaiDuParser爬取百度的数据
    • SinaParser
    • SougouParser
  • 返回解析好的 JSON 格式,统一好了
  • 保存入库

模板模式:

通常叫做模板方法模式(Template Method)

举例–饮料:

  1. 加饮料
  2. 加水
  3. 烧水
  4. 加工
  5. 混合

固定的方法,通常写成抽象方法,让我们自己去实现

举例–JDBCTemplate

​ 今天利用模板模式,自己写一个

模板模式代码:

Member.class
public class Member {
    private String userName;
    private String passWord;
    private int age;

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
JdbcTemplate.class – 手写 JDBCTemplate
public class JdbcTemplate {

    private DataSource dataSource;

    public JdbcTemplate(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    private Connection getConnection() throws Exception {
        return this.dataSource.getConnection();
    }

    private PreparedStatement createPreparedStatement(Connection conn, String sql) throws Exception {
        return conn.prepareStatement(sql);
    }

    private ResultSet executeQuery(PreparedStatement pstmt, Object[] values) throws Exception {
        for (int i = 0; i < values.length; i++) {
            pstmt.setObject(i, values[i]);
        }
        return pstmt.executeQuery();
    }

    private void closeStatement(Statement stmt) throws Exception {
        stmt.close();
    }

    private void closeResultSet(ResultSet rs) throws Exception {
        rs.close();
    }

    private void closeConnection(Connection conn) throws Exception {
        // Spring 中,通常是不会关闭,把它放到连接池中回收

    }

    private List<?> parseResultSet(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;
    }

    public List<?> executeQuery(String sql, RowMapper<?> rowMapper, Object[] values) {
        try {
            // 1. 获取链接
            Connection conn = this.getConnection();
            // 2. 创建语句集
            PreparedStatement pstmt = this.createPreparedStatement(conn, sql);
            // 3. 执行语句集,并且获得结果集
            ResultSet rs = this.executeQuery(pstmt, values);
            // 4. 解析语句集
            List<?> result = this.parseResultSet(rs, rowMapper);

            // 5. 关闭结果集
            this.closeResultSet(rs);
            // 6. 关闭语句集
            this.closeStatement(pstmt);
            // 7. 关闭连接
            this.closeConnection(conn);

            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

//    public abstract Object processResult(ResultSet rs, int rowNum) throws SQLException;
}
RowMapper<T>.class
public interface RowMapper<T> {
    public T mapRow(ResultSet rs, int rowNum) throws Exception;
}
MemberDao.class
/**
 * 解耦
 * 抽象类  >>>>>>>>  实现接口
 * <br>Darian
 **/
public class MemberDao {

    // 为什么不继承,主要是为了解耦
    // 类似于静态代理,静态代理 JDBCTemplate 的一些方法
    private JdbcTemplate jdbcTemplate = new JdbcTemplate(null);
    
    public List<?> query() {
        String sql = "SELECT * FROM t_member";
        return jdbcTemplate.executeQuery(sql, new RowMapper<Object>() {
            public Object mapRow(ResultSet rs, int rowNum) throws Exception {
                Member member = new Member();
                member.setUserName(rs.getString("userName"));
                member.setPassWord(rs.getString("passWord"));
                member.setAge(rs.getInt("age"));
                return member;
            }
        }, null);
    }
}
MemberDaoTest.class
public class MemberDaoTest {
    public static void main(String[] args) {
        MemberDao memberDao = new MemberDao();
        memberDao.query();
    }
}
assets/JdbcTemplate-手写JDBC模板模式类图.png

JdbcTemplate-手写JDBC模板模式类图

assets/模板模式-旅游路线规划.png

模板模式-旅游路线规划

策略模式和模板模式对比

策略模式

  • 只有选择权(由用户选择已有的固定算法)

模板模式

侧重点不是选择,你没得选择,你必须这么做,你可以参与某一部分内容的自定义去改变执行结果,没办法改变执行流程。

来源于: https://javaguide.net

微信公众号:不止极客



这篇关于百万架构师第六课:设计模式:策略模式及模板模式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程