设计模式8.委派模式和模板方法模式

一、委派模式
源码例子:ClassLoader、DispaterSeverlet

委派模式定义
委派模式(Delegate Pattern) 又叫委托模式。它的基本作用就是负责任务的调度和分配,将任务的分配和执行分离开来。可以看做是一种特殊情况下的静态代理的全权代理。
不属于GOF 23种设计模式之一。属于行为型模式。

应用场景

  1. 委派对象本身不知道如何处理一个任务(或一个请求),把请求交给其他对象来处理。
  2. 实现程序的解耦。

类图
在这里插入图片描述

//抽象员工
public interface IEmployee
{
    void doTask(String task);
}
//员工A
public class EmployeeA implements IEmployee
{
    public static String goodAt = "编程";
    @Override
    public void doTask(String task)
    {
        System.out.println("我是员工A,我擅长" + goodAt + ",我开始做" + task);
    }
}
//员工B
public class EmployeeB implements IEmployee {
    public static String goodAt  = "美工";
    @Override
    public void doTask(String task)
    {
        System.out.println("我是员工B,我擅长" + goodAt + ",我开始做" + task);
    }
}

//委派类
public class DelegateLeader implements IEmployee {
    private static Map<String, IEmployee> employeeMap;

    static
    {
        employeeMap = new HashMap<>();
        employeeMap.put(EmployeeA.goodAt, new EmployeeA());
        employeeMap.put(EmployeeB.goodAt, new EmployeeB());
    }

    @Override
    public void doTask(String task)
    {
        if (employeeMap.containsKey(task))
        {
            employeeMap.get(task).doTask(task);
            return;
        }

        System.out.println("超出职责范围,无能为力");
    }
}
//测试
public class Test
{
    public static void main(String[] args) {
        new DelegateLeader().doTask("编程");
        new DelegateLeader().doTask("美工");
        new DelegateLeader().doTask("匪灭");
    }
}
//结果
我是员工A,我擅长编程,我开始做编程
我是员工B,我擅长美工,我开始做美工
超出职责范围,无能为力

**=====================================================**

二、模板方法模式 Template Method Pattern

模板方法模式定义
模板方法模式又叫模板模式,是指定义一个算法的骨架,并允许子类为其中一个或多个步骤提供实现。
模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。
属于行为型设计模式。

模板模式的适用场景
1、 一次性实现一个算法不变的部分,并将可变得行为留给子类来实现。
2、 各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。

样例
在这里插入图片描述

//实现数据库连接池

public class JdbcPool
{
    private String driverClass = "com.mysql.cj.jdbc.Driver";
    private String url = "jdbc:mysql://localhost:3306/sdn?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8";
    private String user = "root";
    private String password = "root";
    private int minIdle = 2;
    private int maxActive = 5;
    private volatile int currentNum = 0;

    private Vector<Connection> pool = new Vector<>();

    private JdbcPool()
    {
        init();
    }

    public static JdbcPool getInstance()
    {
        return InnerClass.INSTANCE;
    }

    private static class InnerClass
    {
        //静态内部类单例
        private static final JdbcPool INSTANCE = new JdbcPool();
    }

    /**
     * 初始化线程池
     */
    private void init()
    {
        try {
            //1. 注册驱动
            Class.forName(driverClass);


            //2. 初始化获取连接
            Connection conn = null;
            for (int i = 1; i < minIdle; i++)
            {
                conn = DriverManager.getConnection(url, user, password);
                pool.add(conn);
                currentNum++;
            }

        }
        catch (Exception ex)
        {
            System.out.println(ex.getMessage());
            System.out.println("线程池初始化失败");
        }
    }

    public Connection getConn()
    {
        Connection conn = null;
        int trytime = 0;
        try {
            while (null == conn) {
                if (trytime >= 3)
                {
                    System.out.println("未获取连接,重试超过3次返回...");
                    break;
                }
                conn = this.getConnection();
                if (null == conn) {
                    Thread.currentThread().sleep(500);
                    trytime++;
                }
            }
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }

        return conn;
    }
    //单独方法,防止死锁
    private synchronized Connection getConnection() throws SQLException
    {
        Connection conn = null;
        if (pool.size() > 0)
        {
            conn = pool.get(0);
            pool.remove(conn);
            System.out.println("获取一个连接");
        }
        else
        {
            if (currentNum < maxActive) {
                conn = DriverManager.getConnection(url, user, password);
                currentNum++;
                System.out.println("新增一个连接");
            }
        }

        return conn;
    }

    public synchronized void release(Connection conn)
    {
        pool.add(conn);
        System.out.println("连接回收放回连接池");
    }
}

//定义统一的转换接口
public interface RowMapper<T> {
    T rowMapper(ResultSet rs, int i);
}

//JDBC查询模板

public abstract class JdbcTemplate<T>
{
    public List<T> executeQuery(String sql, RowMapper<T> mapper, Object[] args) throws SQLException
    {
        //1. 获取连接
        Connection conn = this.getConnection();

        if (null == conn)
        {
            System.out.println("未获取连接!!!!!");
            return null;
        }

        //2. 得到prepared
        PreparedStatement pst = this.preparedStatement(conn, sql);

        //3. 执行查询
        ResultSet result = this.executeQuery(pst, args);

        //4. 返回结果集合
        List<T> list = this.resultMapper(result, mapper);

        //测试延迟放回连接
        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //5. 返回连接
        this.closeConnection(conn, pst, result);

        return  list;
    }

    private List<T> resultMapper(ResultSet rs, RowMapper<T> mapper) throws SQLException
    {
        List<T> list = new ArrayList<>();
        int rownum = 0;
        if (null != rs) {
            while (rs.next())
            {
                //抽象方法实现转换
                list.add(mapper.rowMapper(rs, rownum++));
            }
        }
        return list;
    }

    private void closeConnection(Connection conn, PreparedStatement pst, ResultSet result) throws SQLException {
        JdbcPool.getInstance().release(conn);
        if (null != pst)
        {
            pst.close();
        }

        if (result != pst)
        {
            result.close();
        }
    }

    private ResultSet executeQuery(PreparedStatement pst, Object[] args) throws SQLException
    {
        if (null != args) {
            for (int i = 0; i < args.length; i++) {
                //PreparedStatement 条件从1开始
                pst.setObject(i + 1, args[i]);
            }
        }

        return pst.executeQuery();
    }

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

    private Connection getConnection()
    {
        return JdbcPool.getInstance().getConn();
    }
}
//定义实体类

public class User implements RowMapper<User> {
    private int userid;
    private String username;
    private String roleid;
    private String usercode;
    private String password;
    private Date createTime;

    public int getUserid() {
        return userid;
    }

    public void setUserid(int userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getRoleid() {
        return roleid;
    }

    public void setRoleid(String roleid) {
        this.roleid = roleid;
    }

    public String getUsercode() {
        return usercode;
    }

    public void setUsercode(String usercode) {
        this.usercode = usercode;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Override
    public User rowMapper(ResultSet rs, int i)
    {
        User user = new User();
        try {
            user.setUserid(rs.getInt("userid"));
            user.setUsername(rs.getString("username"));
            user.setUsercode(rs.getString("usercode"));
            user.setPassword(rs.getString("password"));
            user.setRoleid(rs.getString("roleid"));
            user.setCreateTime(rs.getDate("createtime"));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return user;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}

//DAO

public class UserDao extends JdbcTemplate
{
    //通过ID查询用户
    public List<User> queryById(Object[] args)
    {
        String sql = "select * from u_user where userid=?";
        List<User> result = null;
        try
        {
            result = super.executeQuery(sql, new User(), args);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        return result;
    }
}

//Service
public class UserService
{
    private UserDao dao = new UserDao();

    public List<User> queryById(Object[] args)
    {
        return dao.queryById(args);
    }
}
//测试

public class Test
{
    public static void main(String[] args) {
        UserService service = new UserService();

        //1. 验证查询结果
        Object[] conds = new Object[]{1};
        List<User> result = service.queryById(conds);
        System.out.println(result);

        RoleService sev2 = new RoleService();
        List<Role> ret2 = sev2.queryById(null);
        System.out.println(ret2);

        //2. 验证线程池
        /**for (int i = 0; i < 6; i++)
        {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int j = 0; j < 5; j++)
                    {
                        service.queryById(null);
                    }
                }
            }).start();
        }**/
    }
}

//1.结果
获取一个连接
连接回收放回连接池
[{"createTime":"2021-04-06","password":"admin#2021","roleid":"1","usercode":"admin","userid":1,"username":"超级管理员"}]
获取一个连接
连接回收放回连接池
[{"authid":"1,2,3","roleid":1,"rolename":"管理员角色"}, {"authid":"1","roleid":2,"rolename":"访问角色"}]

//2结果
com.lt.architect.templatepattern.Test
获取一个连接
新增一个连接
新增一个连接
新增一个连接
新增一个连接
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
获取一个连接
获取一个连接
获取一个连接
获取一个连接
获取一个连接
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
获取一个连接
获取一个连接
获取一个连接
获取一个连接
获取一个连接
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
获取一个连接
获取一个连接
连接回收放回连接池
获取一个连接
连接回收放回连接池
获取一个连接
获取一个连接
连接回收放回连接池
获取一个连接
连接回收放回连接池
获取一个连接
连接回收放回连接池
连接回收放回连接池
获取一个连接
连接回收放回连接池
获取一个连接
获取一个连接
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
连接回收放回连接池
获取一个连接
连接回收放回连接池
获取一个连接
连接回收放回连接池
获取一个连接
连接回收放回连接池
获取一个连接
连接回收放回连接池
获取一个连接
连接回收放回连接池

Process finished with exit code 0

模板模式的优点

  1. 利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
  2. 将不同的代码放到不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
  3. 把不变的行为写到父类上,去除子类的重复代码,提供了一个很好的代码复用平台,符合开闭原则。

模板模式的缺点
1、类数目的增加,每一个抽象类都需要一个子类实现,这样导致类的个数增加。
2、类数量的增加,间接的增加了系统实现的复杂度。
3、继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值