zoukankan      html  css  js  c++  java
  • 019 委托

    实例:C/C++中的函数指针

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef int(*Calc)(int a, int b);
    
    int Add(int a, int b)
    {
        return a+b;
    }
    
    int Sub(int a, int b)
    {
        return a-b;
    }
    
    int main()
    {
        int x = 100;
        int y = 200;
        int z;
    
        Calc funPiont1 = &Add;
        Calc funPoint2 = &Sub;
    
        z = funPiont1(x,y);
        printf("%d+%d=%d
    ",x,y,z);
    
        z=funPoint2(x,y);
        printf("%d-%d=%d
    ",x,y,z);
    
        system("pause");
        return 0;
    }

    C#中的委托:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace demo2
    {
        class Program
        {
            static void Main(string[] args)
            {
                Calcculator calculator = new Calcculator();
                Action action = new Action(calculator.Report);
                calculator.Report();
                action.Invoke();
                action();
    
                Func<int, int, int> func1 = new Func<int, int, int>(calculator.Add);
                Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);
                int x = 20;
                int y = 12;
                int z = func1(x, y);
                Console.WriteLine(z);
                z = func2(x, y);
                Console.WriteLine(z);
            }
        }
    
        class Calcculator
        {
            public void Report()//报告
            {
                Console.WriteLine("I have 3 methods.");//我有三种方法
            }
    
            public int Add(int a,int b)
            {
                int result = a + b;
                return result;
            }
    
            public int Sub(int a,int b)
            {
                int result = a - b;
                return result;
            }
        }
    }

    C#委托声明(自定义委托)

    检测委托是否是一个类(返回结果表示 委托是一个类):

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace demo2
    {
        class Program
        {
            static void Main(string[] args)
            {
                Type t = typeof(Action);
                Console.WriteLine(t.IsClass);
            }
        }
    }

    自己声明一个委托:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Calculator calculator = new Calculator();
                Calc calc1 = new Calc(calculator.Add);
                Calc calc2 = new Calc(calculator.Sub);
                Calc calc3 = new Calc(calculator.Mul);
                Calc calc4 = new Calc(calculator.Div);
    
                double a = 100;
                double b = 200;
                double c = 0;
                Console.WriteLine(calc1.Invoke(a,b));
                Console.WriteLine(calc2.Invoke(a,b));
                Console.WriteLine(calc3(a,b));
                Console.WriteLine(calc4(a,b));
    
            }
        }
    
        class Calculator
        {
            public double Add(double x, double y)
            {
                return x + y;
            }
    
            public double Sub(double x, double y)
            {
                return x - y;
            }
    
            public double Mul(double x, double y)
            {
                return x * y;
            }
    
            public double Div(double x, double y)
            {
                return x / y;
            }
    
        }
    }

    委托的一般使用

    实例:把方法当做参数传给另一个方法

    正确使用1:模板方法

    • 相当于填空题
    • 常常位于代码中部
    • 委托有返回值
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                ProductFactory productFactory = new ProductFactory();
                WrapFactory wrapFactory = new WrapFactory();
    
                Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
                Func<Product> func2 = new Func<Product>(productFactory.MakeToCar);
    
                Box box1 = wrapFactory.WraProduct(func1);
                Box box2 = wrapFactory.WraProduct(func2);
    
                Console.WriteLine(box1.product.Name);
                Console.WriteLine(box2.product.Name);
            }
        }
        
        class Product//产品
        {
            public string Name { get; set; }
        }
    
        class Box//包装
        {
            public Product product { get; set; }
        }
    
        class WrapFactory//包装工厂
        {
            public Box WraProduct(Func<Product>getProduct)
            {
                Box box = new Box();
                Product product = getProduct.Invoke();
                box.product = product;
                return box;
            }
        }
    
        class ProductFactory//产品工厂
        {
            public Product MakePizza()
            {
                Product product = new Product();
                product.Name = "Pizza";
                return product;
            }
    
            public Product MakeToCar()
            {
                Product product = new Product();
                product.Name = "Toy Car";
                return product;
            }
        }
    }

    正确使用2:回调(callback)

    • 相当于流水线
    • 常常位于代码末尾
    • 委托无返回值
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                ProductFactory productFactory = new ProductFactory();
                WrapFactory wrapFactory = new WrapFactory();
    
                Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
                Func<Product> func2 = new Func<Product>(productFactory.MakeToCar);
    
                Logger logger = new Logger();
                Action<Product> log = new Action<Product>(logger.Log);
    
                Box box1 = wrapFactory.WraProduct(func1,log);
                Box box2 = wrapFactory.WraProduct(func2,log);
    
                Console.WriteLine(box1.product.Name);
                Console.WriteLine(box2.product.Name);
            }
        }
    
        class Logger
        {
            public void Log(Product product)
            {
                Console.WriteLine("Product'{0}' Create at'{1}'.Price is '{2}'.",product.Name,DateTime.UtcNow,product.Price);
            }
        }
    
        class Product//产品
        {
            public string Name { get; set; }
            public double Price { get; set; }
        }
    
        class Box//包装
        {
            public Product product { get; set; }
        }
    
        class WrapFactory//包装工厂
        {
            public Box WraProduct(Func<Product>getProduct,Action<Product>logCallback)
            {
                Box box = new Box();
                Product product = getProduct.Invoke();
                if (product.Price >= 50)
                {
                    logCallback(product);
                }
                box.product = product;
                return box;
            }
        }
    
        class ProductFactory//产品工厂
        {
            public Product MakePizza()
            {
                Product product = new Product();
                product.Name = "Pizza";
                product.Price = 12;
                return product;
            }
    
            public Product MakeToCar()
            {
                Product product = new Product();
                product.Name = "Toy Car";
                product.Price = 100;
                return product;
            }
        }
    }

    注意:难精通+易使用+功能强大的东西,一旦被滥用则后果非常严重

    • 缺点1:这种方法是一种方法级别的紧耦合,现实工作中要慎之又慎.
    • 缺点2:使可读性下降,debug难度增大.
    • 缺点3:把委托回调,异步回调和多线程纠缠在一起,会让代码变得难以阅读和维护.
    • 缺点4:委托使用不当有可能造成内存泄漏和程序性能下降.

    下面是一段滥用委托的例子:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Operation op1 = new Operation();
                Operation op2 = new Operation();
                Operation op3 = new Operation();
    
                op3.InnerOperation = op2;
                op2.InnerOperation = op1;
    
                op3.Operate(new object, null, null);
                //问题1:如果传入的两个参数都为null,失败返回的结果是什么?答:内层操作会调用外层的回调!
                //问题2:如果传入的两个参数不为null,会出现什么情况?答:所有默认callback都被"穿透性"屏蔽!
            }
        }
    
        class Operation
        {
            public Action DefaultSuccessCallback { get; set; }
            public Action DefaultFailureCallback { get; set; }
            public Operation InnerOperation { get; set; }
    
            public object Operate(object input,Action successCallback,Action failureCallback)
            {
                if (successCallback == null)
                {
                    successCallback = this.DefaultSuccessCallback;
                }
    
                if (failureCallback == null)
                {
                    failureCallback = this.DefaultFailureCallback;
                }
    
                object result = null;
                try
                {
                    result = this.InnerOperation(input, successCallback, failureCallback);
                }
                catch
                {
    
                    failureCallback.Invoke();
                }
    
                successCallback.Invoke();
                return result;
            }
        }
    }

    委托的高级使用

    • 多播委托

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
                Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
                Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
    
                Action action1 = new Action(stu1.DoHomework);
                Action action2 = new Action(stu2.DoHomework);
                Action action3 = new Action(stu3.DoHomework);
    
                //单播委托
                //action1.Invoke();
                //action2.Invoke();
                //action3.Invoke();
    
                //多播委托
                action1 += action2;
                action1 += action3;
    
                action1.Invoke();
            }
        }
    
        class Student
        {
            public int ID { get; set; }
            public ConsoleColor PenColor { get; set; }
    
            public void DoHomework()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.ForegroundColor = this.PenColor;
                    Console.WriteLine("Student {0} doing homeword {1} hour(s)",this.ID,i);
                    Thread.Sleep(1000);
                }
            }
        }
    }
    • 隐式异步调用

      • 同步与异步简介
        • 中英文语言差异
        • 同步:你做完了我(在你的基础上)接着做.
        • 异步:咱们两个同时做(相当于汉语中的"同步进行")
      • 同步调用与异步调用的对比
        • 每一个运行的程序是一个进程(process)
        • 每一个进程都可以有一个或多个线程(thread)
        • 同步调用实在同个线程内
        • 异步调用的底层机理是多线程
        • 串行==同步==单线程, 并行==异步==多线程
      • 隐式多线程VS显示多线程
        • 直接同步调用:使用方法名
        • 简介同步调用:使用单播/多播委托的invoke方法
        • 隐式异步调用:使用委托begininvoke
        • 显示异步调用:使用thread或task

    同步直接调用实例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
                Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
                Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
    
                stu1.DoHomework();
                stu2.DoHomework();
                stu3.DoHomework();
    
                for (int i = 0; i < 10; i++)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("Main thread{0}.", i);
                    Thread.Sleep(1000);
                }
            }
        }
    
        class Student
        {
            public int ID { get; set; }
            public ConsoleColor PenColor { get; set; }
    
            public void DoHomework()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.ForegroundColor = this.PenColor;
                    Console.WriteLine("Student {0} doing homeword {1} hour(s)", this.ID, i);
                    Thread.Sleep(1000);
                }
            }
        }
    }

    同步单播间接调用实例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
                Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
                Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
    
                Action action1 = new Action(stu1.DoHomework);
                Action action2 = new Action(stu2.DoHomework);
                Action action3 = new Action(stu3.DoHomework);
    
                action1.Invoke();
                action2.Invoke();
                action3.Invoke();
    
                for (int i = 0; i < 10; i++)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("Main thread{0}.", i);
                    Thread.Sleep(1000);
                }
            }
        }
    
        class Student
        {
            public int ID { get; set; }
            public ConsoleColor PenColor { get; set; }
    
            public void DoHomework()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.ForegroundColor = this.PenColor;
                    Console.WriteLine("Student {0} doing homeword {1} hour(s)", this.ID, i);
                    Thread.Sleep(100);
                }
            }
        }
    }

    同步多播间接调用:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
                Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
                Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
    
                Action action1 = new Action(stu1.DoHomework);
                Action action2 = new Action(stu2.DoHomework);
                Action action3 = new Action(stu3.DoHomework);
    
                action1 += action2;
                action1 += action3;
    
                action1.Invoke();
    
                for (int i = 0; i < 10; i++)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("Main thread{0}.", i);
                    Thread.Sleep(1000);
                }
            }
        }
    
        class Student
        {
            public int ID { get; set; }
            public ConsoleColor PenColor { get; set; }
    
            public void DoHomework()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.ForegroundColor = this.PenColor;
                    Console.WriteLine("Student {0} doing homeword {1} hour(s)", this.ID, i);
                    Thread.Sleep(100);
                }
            }
        }
    }

    隐式异步调用例子:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
                Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
                Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
    
                Action action1 = new Action(stu1.DoHomework);
                Action action2 = new Action(stu2.DoHomework);
                Action action3 = new Action(stu3.DoHomework);
    
                action1.BeginInvoke(null, null);
                action2.BeginInvoke(null, null);
                action3.BeginInvoke(null, null);
    
                for (int i = 0; i < 10; i++)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("Main thread{0}.", i);
                    Thread.Sleep(100);
                }
            }
        }
    
        class Student
        {
            public int ID { get; set; }
            public ConsoleColor PenColor { get; set; }
    
            public void DoHomework()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.ForegroundColor = this.PenColor;
                    Console.WriteLine("Student {0} doing homeword {1} hour(s)", this.ID, i);
                    Thread.Sleep(100);
                }
            }
        }
    }

    显示异步调用1:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
                Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
                Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
    
                //古老的方式
                Thread thread1 = new Thread(new ThreadStart(stu1.DoHomework));
                Thread thread2 = new Thread(new ThreadStart(stu2.DoHomework));
                Thread thread3 = new Thread(new ThreadStart(stu3.DoHomework));
    
                thread1.Start();
                thread2.Start();
                thread3.Start();
    
                for (int i = 0; i < 10; i++)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("Main thread{0}.", i);
                    Thread.Sleep(100);
                }
            }
        }
    
        class Student
        {
            public int ID { get; set; }
            public ConsoleColor PenColor { get; set; }
    
            public void DoHomework()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.ForegroundColor = this.PenColor;
                    Console.WriteLine("Student {0} doing homeword {1} hour(s)", this.ID, i);
                    Thread.Sleep(100);
                }
            }
        }
    }

    显示异步调用2:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
                Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
                Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };
    
                Task task1 = new Task(new Action(stu1.DoHomework));
                Task task2 = new Task(new Action(stu2.DoHomework));
                Task task3 = new Task(new Action(stu3.DoHomework));
    
                task1.Start();
                task2.Start();
                task3.Start();
    
                for (int i = 0; i < 10; i++)
                {
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine("Main thread{0}.", i);
                    Thread.Sleep(100);
                }
            }
        }
    
        class Student
        {
            public int ID { get; set; }
            public ConsoleColor PenColor { get; set; }
    
            public void DoHomework()
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.ForegroundColor = this.PenColor;
                    Console.WriteLine("Student {0} doing homeword {1} hour(s)", this.ID, i);
                    Thread.Sleep(100);
                }
            }
        }
    }
    •  应该适时地使用接口(interface)取代一些委托的操作
      • java完全地使用接口取代了委托的功能.

    使用接口取代委托的例子:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace demo2
    {
        public delegate double Calc(double x, double y);
    
        class Program
        {
            static void Main(string[] args)
            {
                IProductFactory pizzaFactory = new PizzaFactory();
                IProductFactory toycarFactory = new ToCarFactory();
                WrapFactory wrapFactory = new WrapFactory();
     
                Box box1 = wrapFactory.WraProduct(pizzaFactory);
                Box box2 = wrapFactory.WraProduct(toycarFactory);
    
                Console.WriteLine(box1.product.Name);
                Console.WriteLine(box2.product.Name);
            }
        }
    
        interface IProductFactory
        {
            Product Make();
        }
    
        class PizzaFactory : IProductFactory
        {
            public Product Make()
            {
                Product product = new Product();
                product.Name = "Pizza";
                return product;
            }
        }
    
        class ToCarFactory : IProductFactory
        {
            public Product Make()
            {
                Product product = new Product();
                product.Name = "Toy Car";
                return product;
            }
        }
    
        class Product//产品
        {
            public string Name { get; set; }
        }
    
        class Box//包装
        {
            public Product product { get; set; }
        }
    
        class WrapFactory//包装工厂
        {
            public Box WraProduct(IProductFactory productFactory)
            {
                Box box = new Box();
                Product product = productFactory.Make();
                box.product = product;
                return box;
            }
        }
    
        class ProductFactory//产品工厂
        {
            public Product MakePizza()
            {
                Product product = new Product();
                product.Name = "Pizza";
                return product;
            }
    
            public Product MakeToCar()
            {
                Product product = new Product();
                product.Name = "Toy Car";
                return product;
            }
        }
    }
  • 相关阅读:
    CSS 设置table下tbody滚动条
    PHP图片上传程序(完整版)
    Nginx无法监听虚拟VIP的问题报:99: Cannot assign requested address
    当切换用户时出现-bash-4.1$
    mysql 启动报错Host name could not be resolved解决办法
    设置博客园标题样式
    五步解决windows系统慢的问题
    Centos7下yum安装软件报错解决办法
    windows下使用mysqlbinlog做数据恢复时出现mysqlbinlog: File 'D:MariaDB' not found (Errcode: 2)
    Microsoft SQL Server Management Studio连接后报“ viewInfo (Microsoft.SqlServer.Management.SqlStudio.Expl”
  • 原文地址:https://www.cnblogs.com/YiShen/p/9889380.html
Copyright © 2011-2022 走看看