● 委托(delegate)是函数指针的“升级版”
○ 示例:C/C++ 中的函数指针
● 一切皆地址
○ 变量(数据)是以某个地址为起点的一段内存中所存储的值
○ 函数(算法)是以某个地址为起点的一段内存中所存储的一组机器语言指令
● 直接调用与间接调用
○ 直接调用:通过函数名来调用函数,CPU 通过函数名直接获得函数所在地址并开始执行 -> 返回
○ 间接调用:通过函数指针来调用函数,CPU 通过读取函数指针存储的值获得函数所在地址并开始执行 -> 返回
● Java 中没有与委托相对应的功能实体
● 委托的简单使用
○ Action 委托
○ Func 委托
class Demo_Delegate
{
public void test()
{
Demo19_Calculator demo19_Calculator = new Demo19_Calculator();
Action action = new Action(demo19_Calculator.Report);
action.Invoke();
action();
Func<int,int,int> func = new Func<int, int, int>(demo19_Calculator.Add);
Console.WriteLine(func(1, 1));
}
}
class Demo19_Calculator
{
public void Report()
{
Console.WriteLine("I have 3 methods");
}
public int Add(int a,int b)
{
return a + b;
}
public int Sub(int a, int b)
{
return a - b;
}
}
使用delegate时:
根据delegate声明位置其生效范围也不相同
所以放在命名空间的最高层更好一些(?)
Func_Double multi = demo19_Calculator.Mul;
Console.WriteLine(multi(3, 3));
Func_Double devide = new Func_Double(demo19_Calculator.Div);//这样更有可读性??
Console.WriteLine();
委托的一般使用
模板方法:感觉有点类似于C++中STL的一些使用方法
回调方法:安卓全是这种
模板方法:
执行过程
WrapFactory wrapFactory = new WrapFactory();
ProductFactory productFactory = new ProductFactory();
Box box1 = wrapFactory.WrapProduct(productFactory.Produce, "apple");
Box box2 = wrapFactory.WrapProduct(productFactory.Produce, "banana");
相关类的实现
class WrapFactory
{
public Box WrapProduct(Func<string,Product> getProduct,string productName)
{
Box box = new Box();
box.product = getProduct.Invoke(productName);
return box;
}
}
class ProductFactory
{
public Product Produce(string productName)
{
Console.WriteLine("made a "+productName);
return new Product() { name = productName };
}
}
回调方法:
class WrapFactory
{
public Box WrapProduct(Func<string,Product> getProduct,string productName ,Action<Product> logCallBack)
{
Box box = new Box();
box.product = getProduct.Invoke(productName);
if(box.product.price > 30)
{
logCallBack(box.product);
}
return box;
}
}
class ProductFactory
{
public Product Produce(string productName)
{
Console.WriteLine("made a "+productName);
return new Product() { name = productName,price = productName[0]-' ' };
}
}
class Logger
{
public static void Log(Product product)
{
Console.WriteLine("Product {0} created at {1}.Price is {2}", product.name, DateTime.Now, product.price);
}
}
本质上就是多用了一个委托类型的参数用于存储回调函数供使用
委托的高级使用:
示例:
class Demo_MultiCast
{
public void test()
{
Demo19_Student student1 = new Demo19_Student() { ID = 1, PenColor = ConsoleColor.Red };
Demo19_Student student2 = new Demo19_Student() { ID = 2, PenColor = ConsoleColor.Green };
Demo19_Student student3 = new Demo19_Student() { ID = 3, PenColor = ConsoleColor.Blue };
Action action1 = student1.DoHomeWork;
Action action2 = student2.DoHomeWork;
Action action3 = student3.DoHomeWork;
//action1 += action2;
//action1 += action3;
//action1();//同步调用
//action1.BeginInvoke(null, null);//隐式异步
//action2.BeginInvoke(null, null);
//action3.BeginInvoke(null, null);//因为争抢ForegroundColor导致资源冲突,未能使得颜色一定对应于学生的PenColor
//Thread thread1 = new Thread(new ThreadStart(student1.DoHomeWork));//显式异步调用
//Thread thread2 = new Thread(new ThreadStart(student2.DoHomeWork));
//Thread thread3 = new Thread(new ThreadStart(student3.DoHomeWork));
//thread1.Start();
//thread2.Start();
//thread3.Start();
//Task task1 = new Task(student1.DoHomeWork);//显式异步调用
//Task task2 = new Task(student2.DoHomeWork);
//Task task3 = new Task(student3.DoHomeWork);
//task1.Start();
//task2.Start();
//task3.Start();
Console.ForegroundColor = ConsoleColor.White;
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main Thread {0}",i);
Thread.Sleep(500);
}
}
}
class Demo19_Student
{
public int ID { get; set; }
public ConsoleColor PenColor { get; set; }
public void DoHomeWork()
{
for(int i = 0; i < 5; i++)
{
Console.ForegroundColor = PenColor;
Console.WriteLine("Student {0} is doing homework for {1} hours", ID, i);
Thread.Sleep(500);
}
}
}
写代码就完事了
接口的简单示范:
自己对比委托和接口的使用方法的具体差异
class WrapFactory
{
public Box WrapProduct(Func<string,Product> getProduct,string productName ,Action<Product> logCallBack)
{
Box box = new Box();
box.product = getProduct.Invoke(productName);
if(box.product.price > 30)
{
logCallBack(box.product);
}
return box;
}
public Box WrapProduct(IProductFactory productFactory, string productName, Action<Product> logCallBack)
{
Box box = new Box();
box.product = productFactory.Make(productName);
if (box.product.price > 30)
{
logCallBack(box.product);
}
return box;
}
}
class ProductFactory:IProductFactory
{
public Product Produce(string productName)
{
Console.WriteLine("made a " + productName);
return new Product() { name = productName,price = productName[0]-' ' };
}
public Product Make(string productName)
{
return new Product() { name = productName, price = productName[0] - ' ' };
}
}
具体使用时(品)
Box box1 = wrapFactory.WrapProduct(productFactory.Produce, "apple", Logger.Log);
Box box2 = wrapFactory.WrapProduct(productFactory, "banana", Logger.Log);