委托:把方法当作参数传递给其他方法
模板方法 ——“借用”指定的外部方法来产生结果
优点:实现了代码的重复使用,提高代码效率
特点:
1. 相当于填空题
2. 常位于代码中部
3. 委托有返回值
代码阅读顺序,最后阅读Main函数,先看下面的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Security.Cryptography.X509Certificates;
namespace DelegateExample
{
#region 模板方法——间接调用
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.MakeToyCar);
//调用模板方法
//wrapFactory.WrapProduct(func1);返回值是box类型,需要一个box类型接收
Box box1 = wrapFactory.WrapProduct(func1);
Box box2 = wrapFactory.WrapProduct(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; }//包装箱具有一个Product类型的属性,就是这个箱子里包装的产品
}
class WrapFactory//这个类负责把产品包装进盒子给用户
{
//模板方法
public Box WrapProduct(Func<Product> getProduct)//接受一个委托类型的参数
{
//这个委托类型是Func,Func封装的方法可以返回一个Product类型的对象
Box box = new Box();
Product product = getProduct.Invoke();
//getProduct委托的返回类型就是Product类型的,调用完肯定得到一个Product类型对象
box.Product = product;//把box.Product这个属性的值设为刚才拿到的product
return box;
}
//使用模板方法的好处是我的工厂类,box类都不需要再动了,只需要增加产品类即可
//最大限度实现了代码的重复使用
}
//生产产品的工厂
class ProductFactory
{
public Product MakePizza()//生产披萨
{
Product product = new Product();
product.Name = "Pizza";
return product;
}
public Product MakeToyCar()//生产小汽车
{
Product product = new Product();
product.Name = "ToyCar";
return product;
}
}
#endregion
}
回调函数——调用指定的外部方法
特点:
1. 相当于“流水线”
2. 常位于代码末尾
3. 委托无返回值
以上面的代码为基础,增加回调函数如下:
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.MakeToyCar);
//声明Log实例
Logger logger = new Logger();
Action<Product> log = new Action<Product>(logger.Log);
//调用模板方法
//wrapFactory.WrapProduct(func1);返回值是box类型,需要一个box类型接收
Box box1 = wrapFactory.WrapProduct(func1,log);
Box box2 = wrapFactory.WrapProduct(func2,log) ;
//log方法在生产产品的时候就会执行,所以会比产品信息先打印在控制台,且只打印价格大于50的玩具车
Console.WriteLine(box1.Product.Name);
Console.WriteLine(box2.Product.Name);
}
}
class Logger//记录程序状态,判断程序异常
{
public void Log(Product product)
{
Console.WriteLine("Product'{0}'creat at {1}.Price is {2}.",product.Name,DateTime.Now,product.Price);
//将这个Log方法以回调函数的方式传递回模板方法里
}
}
class Product
{
public string Name { get; set; }//产品
public double Price { get;set; }//价格
}
class Box
{
public Product Product { get; set; }//包装箱具有一个Product类型的属性,就是这个箱子里包装的产品
}
class WrapFactory//这个类负责把产品包装进盒子给用户
{
//模板方法
public Box WrapProduct(Func<Product> getProduct,Action<Product> logCallback)//对于没有返回值的方法应该使用Action委托
{
Box box = new Box();
Product product = getProduct.Invoke();
//添加逻辑决定是不是调用这个回调方法,假设产品价格大于50元时记录一下
if (product.Price>=50)
{
logCallback(product);
}
box.Product = 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 MakeToyCar()//生产小汽车
{
Product product = new Product();
product.Name = "ToyCar";
product.Price = 100;
return product;
}
}
结果如下:
无论是模板方法还是回调函数,本质都是一样的,用委托类型的参数,封装一个外部的方法然后把这个方法传进方法的内部进行间接调用