委托的使用

  • 委托是一种类,所以声明的时候尽量和其他类保持平级的位置
  • 委托与所封装的方法必须“类型兼容”,也就是返回值的数据类型一致,参数列表个数和数据类型上一致

    delegate double Calc(double x,double y)//委托封装方法的类型

         double Add(double x,double y)//方法


一般使用委托,是为了把方法作为参数传到另一个方法里,这样主方法,里面套了个方法,就能动了。有两种使用方法

1.模板方法:借用指定的外部方法来产生结果

  • 相当于“填空题”
  • 常常位于代码中部
  • 委托带有返回值

2.回调方法:回调方法,调用制定的外部方法

  • 相当于“流水线”
  • 常常位于代码末尾
  • 委托无返回值
class Program
    {
        static void Main(string[] args)
        {
            //IProductFactory pizzaFactory = new PizzaFactory();
            //IProductFactory toycarFactory = new ToyCarFactory();

            ProductFactory productFactory = new ProductFactory();
            WrapFactory wrapFactory = new WrapFactory();
            Logger logger = new Logger();

            Action<Product> log = new Action<Product>(logger.Log);//Action委托实例封装了logger

            Func<Product> func1 = new Func<Product>(productFactory.MakePizza);//Func委托实例封装了ProductFactory的方法
            Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);


            Box box = wrapFactory.WrapProduct(func1, log);//调用模板方法(主方法)
            Box box1 = wrapFactory.WrapProduct(func2, log);

            //Box box = wrapFactory.WrapProduct(pizzaFactory);
            //Box box1 = wrapFactory.WrapProduct(pizzaFactory);
             Console.WriteLine(box.Product.Name);
             Console.WriteLine(box1.Product.Name);
             Console.ReadLine();
        }
    }

    interface IProductFactory
    {
        Product Make();
    }
    class PizzaFactory : IProductFactory
    {
        public Product Make()
        {
            Product product = new Product();//
            product.Name = "Pizza";
            product.Price = 12;
            return product;
        }
    }
    class ToyCarFactory : IProductFactory
    {
        
           public Product Make()
        {
            Product product = new Product();
            product.Name = "ToyCar";
            product.Price = 100;
            return product;
        }
        
    }   
    class Logger
    { 
    public void Log(Product product)
        {
            Console.WriteLine("Product ‘{0} created 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 WrapProduct(IProductFactory productFactory)//用接口重构委托
        //{
        //    Box box = new Box();
        //    Product product = productFactory.Make();

        //    //if (product.Price >= 50)
        //    //{
        //    //    logCallback(product);
        //    //}
        //    //box.Product = product;
        //    return box;
        //}
        public Box WrapProduct(Func<Product> getProduct, Action<Product> logCallback)//模板方法,好处在于Product,Box,都可以不动,只在生产产品时不断添加方法
        {
            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 MakeToyCar()
        {
            Product product = new Product();
            product.Name = "ToyCar";
            product.Price = 100;
            return product;
        }
    }

  

 缺点

  • 方法级别的耦合,违反设计模式
  • 可读性下降,debug难度增加
  • 委托回调,异步调用和多线程放在一起,会让代码难以阅读和维护
  • 使用不当内存泄漏,委托引用了一个方法,如果这个方法是实例方法,那委托会一直占用这个实例方法导致内存无法释放实例
posted @ 2019-07-19 23:52  拎着红杯子的黄鸭子  Views(211)  Comments(0Edit  收藏  举报