• 任务交给谁?委派模式告诉你最佳选择!



    一、概念

    1. 委派模式(Delegate Pattern)又叫委托模式,是一种面向对象的设计模式。
    2. 委派模式是一种行为模式,不属于GOF23种设计模式之中
    3. 基本作用是负责任务的调度,是一种特殊的静态代理。

    二、角色

    抽象任务角色(Task):定义一个抽象接口,它有若干实现类。
    委派者角色(Delegate):负责在各个具体角色实例之间做出决策,并判断并调用具体实现的方法。
    具体任务角色(Concrete) :真正执行任务的角色

    现实场景:老板(Boss)给项目经理(Leader)下达任务,项目经理会根据实际情况给每个员工派发工作任务,待员工把工作任务完成之后,再由项目经理汇报工走进度和结果给老板。

    三、代码实现

    创建IEmployee员工接口:

    public interface IEmployee {
        /**
         * 执行任务
         * @param task
         */
        void doing(String task);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建员工EmployeeA类:

    public class EmployeeA  implements IEmployee{
        protected String goodAt="编程";
        @Override
        public void doing(String task) {
            System.out.println("我是员工A,我擅长"+goodAt+",我现在开始做"+task+"工作");
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    创建员工EmployeeB类

    public class EmployeeB implements IEmployee{
        protected String goodAt="平面设计";
        @Override
        public void doing(String task) {
            System.out.println("我是员工B,我擅长"+goodAt+",我现在开始做"+task+"工作");
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    创建项目经理Leader类:

    public class Leader implements IEmployee{
    
        private Map<String, IEmployee> employee=new HashMap<>();
    
        @SuppressWarnings("all")
        public Leader(){
            employee.put("爬虫",new EmployeeA());
            employee.put("海报图",new EmployeeB());
        }
        @Override
        public void doing(String task) {
            if(!employee.containsKey(task)){
                System.out.println("这个任务"+task+"超出我的能力范围");
                return;
            }
            employee.get(task).doing(task);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    创建Boss下达命令:

    public class Boss {
        public void command(String task,Leader leader) {
          leader.doing(task);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    测试代码:

    public class Test {
        public static void main(String[] args) {
           new Boss().command("海报图",new Leader());
           new Boss().command("爬虫",new Leader());
           new Boss().command("卖手机",new Leader());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    四、委派模式在源码中的体现

    JDK的双亲委派机制

     protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException
        {
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                Class<?> c = findLoadedClass(name);
                if (c == null) {
                    long t0 = System.nanoTime();
                    try {
                        if (parent != null) {
                            c = parent.loadClass(name, false);
                        } else {
                            c = findBootstrapClassOrNull(name);
                        }
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from the non-null parent class loader
                    }
    
                    if (c == null) {
                        // If still not found, then invoke findClass in order
                        // to find the class.
                        long t1 = System.nanoTime();
                        c = findClass(name);
    
                        // this is the defining class loader; record the stats
                        sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        sun.misc.PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    Method中的invoke方法

    @CallerSensitive
        public Object invoke(Object obj, Object... args)
            throws IllegalAccessException, IllegalArgumentException,
               InvocationTargetException
        {
            if (!override) {
                if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                    Class<?> caller = Reflection.getCallerClass();
                    checkAccess(caller, clazz, obj, modifiers);
                }
            }
            MethodAccessor ma = methodAccessor;             // read volatile
            if (ma == null) {
                ma = acquireMethodAccessor();
            }
            return ma.invoke(obj, args);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    具体实现类:

    class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
        private MethodAccessorImpl delegate;
    
        DelegatingMethodAccessorImpl(MethodAccessorImpl var1) {
            this.setDelegate(var1);
        }
    
        public Object invoke(Object var1, Object[] var2) throws IllegalArgumentException, InvocationTargetException {
            return this.delegate.invoke(var1, var2);
        }
    
        void setDelegate(MethodAccessorImpl var1) {
            this.delegate = var1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Spring中的DispatchServlet也用到了委派模式。

    五、委派模式的优缺点

    优点

    通过任务委派能够将一个大型的任务细化,然后通过统一管理这些子任务的完成情况实现任务的跟进,能够加快任务执行的效率。

    缺点

    任务委派模式需要根据任务的复杂程度进行不同的改变,在任务比较复杂的情况下可能需要进行多重委派,容易造成紊乱。

  • 相关阅读:
    一文理解深度学习框架中的InstanceNorm
    【C#异步】异步多线程的本质,上下文流转和同步
    【C语言基础】Chap. 2. 基本概念
    前端请求到 SpringMVC 的处理流程
    提升提测质量之研测共建 | 京东云技术团队
    Java 定时任务-最简单的3种实现方法
    JG/T 543-2018 铝塑共挤门窗检测
    你能猜出这是什么代码吗
    sql存储引擎
    springboot使用filter增加全局traceId,方便日志查找
  • 原文地址:https://blog.csdn.net/Hi_alan/article/details/134429613