委托
| 委托的定义和使用
作用
把方法作为函数来进行传递,用到委托。委托是一个类型,这个类型可以赋值一个方法的引用。
C# 的委托通过
delegate
关键字来声明。
声明委托
(1)
delegate void MyDelegate1( int x )
(2)
delegate void MyDelegate2<T>( T x )
使用委托
(1)
MyDelegate1 mydelegate = new MyDelegate( func )
(2)
MyDelegate1 mydelegate = func
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BaseDelegate : MonoBehaviour
{
public delegate void ShowDelegate();
public delegate void ShowDelegate2(int a, int b);
public delegate int ShowDelegate3();
public delegate void ShowDelegate4<T>(T a);
void Start()
{
ShowDelegate show = Show1;
show();
//show.Invoke();
ShowDelegate2 show2 = Show2;
show2(1, 2);
ShowDelegate3 show3 = Show3;
int a = show3();
Debug.Log(a);
ShowDelegate4<string> show4 = Show4;
show4("Hello World");
}
private void Show1()
{
Debug.Log("Show1");
}
private void Show2(int a, int b)
{
Debug.Log("Show2 -> a+b:" + (a + b));
}
private int Show3()
{
return 1000;
}
private void Show4(string a)
{
Debug.Log("Show4 -> a:" + a);
}
}
| 系统内置 Action
委托
需要命名空间: using Ststem;
什么是Action委托:
Action<T>
是.NET Framework内置的泛型委托,可以使用 Action<T>
委托以参数形式传递方法,而不用显示声明自定义的委托。封装的方法必须与此委托定义的方法签名相对时应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并且不能有返回值。 还有一种是非泛型委托 Action
。
注意点:
Action
委托至少 0 个参数,至多 16 个参数,无返回值Action
表示无参,无返回值的委托Action< int, string>
表示有传入参数 int,string 无返回值的委托Action< int, string, bool>
表示有传入参数 int,string,bool 无返回值的委托Action< int, int, int, int>
表示有传入 4 个 int 型参数,无返回值的委托
演示:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SystemAction : MonoBehaviour
{
void Start()
{
Action action1 = Show1;
action1();
Action<int, int> action2 = Show2;
action2(1, 2);
//Action<
}
void Show1()
{
Debug.Log("Show1");
}
void Show2(int arg1, int arg2)
{
Debug.Log("Action:" + (arg1 + arg2));
}
}
| 系统内置 Func
委托
什么是 Func
委托:
Func 是 .NET Framework 内置的带有返回类型的泛型委托。
注意点:
Func
:至少 0 个传入参数,至多16个传入参数,根据返回值 泛型 返回。必须有 返回值,不可void。Func<int>
:表示没有传入参数,返回值为 int 类型的委托。Func<object,string,int>
:表示传入参数为为object,string ,返回值为 int 类型的委托。Func<object,string,int>
:表示传入参数为为object,string,返回值为 int 类型的委托。Func<T1,T2..T3,int>
: 表示传入参数为T1, T2..T3(泛型),返回值为 int 类型的委托。System.Func
可以不带参数,但是必须带一个返回值System.Func
若是调用的多个泛型的委托定义,最后的参数的数据类型 是函数的返回值类型,需要保持一致;非最后一个泛型T的声明,需要与实现函数的参数个数及类型保持一致
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class SystemFunc : MonoBehaviour
{
void Start()
{
Func<string> func1 = Show1;
string a = func1();
Debug.Log(a);
//Func<string, int> func2 = Show2;
Func<int,string> func2 = Show2;
string b = func2(1000);
Debug.Log(b);
//Func<
}
string Show1()
{
return "Show1";
}
//int Show2(string a)
//{
// return int.Parse(a);
//}
string Show2(int a)
{
return a.ToString();
}
}
| 匿名方法、event 事件、多播委托
什么是匿名方法:
- 没有名字的方法称之为匿名方法
什么是 Event 事件:
event 事件本身就是一种委托,只是该委托只能作为类的成员,且不可在类外进行调用
注意点
- (1)
- event 事件 只允许作为类的成员变量 且仅在类的内部使用才可以,外部不得直接调用。
- (2)
- 当作为 A 类的成员
event
事件 在外部类赋值时,只能通过+=
的方法; - 而对于 普通的
Action
则可以= / += -=
的方式进行赋值
- 当作为 A 类的成员
- (1)
什么是多播委托:
在 C# 语言中多播委托是指在一个委托中注册多个方法,在注册方法时可以在委托中使用 加号运算符 或者 减号运算符 来实现添加或者撤销方法
注意点
+= & -=
委托属于引用类型,引用类型的默认值是 null,直接使用的话会报错空异常;所以在使用之前需要先判断委托对象(引用对象)是否为空
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class MyEventClass
{
public event Action eventAction;
public Action defaultAction;
public void Send()
{
if(eventAction != null)
{
eventAction();
}
}
}
public class BoardCast : MonoBehaviour
{
//event Action action;
void Start()
{
//Action action = Show1;
//Action action = delegate ()
//{
// Debug.Log("匿名函数 被执行");
//};
//action();
//Action action = Show1;
//action += Show2;
//action -= Show2;
//action -= Show1;
//if(action != null)
// action();
//action = Show1;
//action();
MyEventClass myClass = new MyEventClass();
myClass.eventAction += Show1;
myClass.Send();
//myClass.eventAction(); error
//myClass.eventAction -= Show1;
myClass.defaultAction = Show2;
myClass.defaultAction();
}
private void Show1()
{
Debug.Log("Show1 被执行");
}
private void Show2()
{
Debug.Log("Show2 被执行");
}
}
设计模式相关内容
| 设计模式(Design pattern)
分类:
创建型模式:共 5 种 - 工厂方法模式 、抽象工厂模式 、单例模式 、建造者模式 、原型模式
结构型模式:共 7 种 - 适配器模式 、装饰器模式 、代理模式 、外观模式 、桥接模式 、组合模式 、享元模式
行为型模式:共 11 种 - 策略模式 、模板方法模式 、观察者模式 、迭代子模式 、责任链模式 、命令模式 、备忘录模式 、状态模式 、访问者模式 、中介者模式 、解释器模式
| 单例模式
即所谓的一个类只能有一个实例,也就是类只能在内部实例一次,然后提供这一实例,外部无法对此类实例化。多用在 管理器
特点:
实例全局唯一
static
静态变量 属于全局,并不属于类对象本身
实例只能在类的内部发生
- 需要将构造函数私有化
需要提供一个供外部访问的变量
只能自己创建自己的唯一实例
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MySingleton
{
private static MySingleton _instance;
public static MySingleton instance
{
get //初始化
{
if (_instance == null)
{
_instance = new MySingleton();
}
return _instance;
}
}
private MySingleton()
{
Debug.Log("构造函数执行");
}
public void Show()
{
Debug.Log("Show");
}
}
public class Singleton : MonoBehaviour
{
void Start()
{
//MySingleton single1 = new MySingleton();
//MySingleton single2 = new MySingleton();
//MySingleton single3 = new MySingleton();
//Debug.Log("single1 =" + single1.GetHashCode() + ",single2 =" + single2.GetHashCode() + ",single3 =" + single3.GetHashCode());
MySingleton single1 = MySingleton.instance;
single1.Show();
MySingleton single2 = MySingleton.instance;
single2.Show();
MySingleton single3 = MySingleton.instance;
single3.Show();
Debug.Log("single1 =" + single1.GetHashCode() + ",single2 =" + single2.GetHashCode() + ",single3 =" + single3.GetHashCode());
}
}
| 观察者模式
有时被称为 发布 / 订阅模式,观察者定义了一种 一对多 的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。此种模式通常被用来实现事件处理系统。
特点: 发布者 + 订阅者 = 观察者模式
观察者模式相关博文:【Unity与23种设计模式】观察者模式(Observer) - Lumious - 博客园
演示:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
/*
* 观察者模式
* 需求:
* 野猫来了,老鼠 A B C 惊吓逃走
*/
public class Animal
{
protected string Name;
public Animal(string name)
{
this.Name = name;
}
public virtual void Run()
{
}
}
public class Cat : Animal
{
public Action actions; // 发布者
public Cat(string name): base(name)
{
}
public void Coming(/*Animal mouseA, Animal mouseB, Animal mouseC, Animal mouseD*/)
{
Debug.Log(Name + "来了");
//mouseA.Run();
//mouseB.Run();
//mouseC.Run();
//mouseD.Run();
if (actions != null)
{
actions(); // 通过 多播委托 实现一对多的关系
}
this.Run();
}
public override void Run()
{
Debug.Log(Name + "开始追三只老鼠...");
}
}
public class Mouse : Animal
{
public Mouse(string name,Cat cat) : base(name)
{
cat.actions += this.Run; // 订阅者
}
public override void Run()
{
Debug.Log(Name + "逃跑");
}
}
#region Temp
//public class MouseB : Animal
//{
// public MouseB(string name) : base(name)
// {
// }
// public override void Run()
// {
// Debug.Log(Name + "逃跑");
// }
//}
//public class MouseC : Animal
//{
// public MouseC(string name) : base(name)
// {
// }
// public override void Run()
// {
// Debug.Log(Name + "逃跑");
// }
//}
#endregion
public class Visit : MonoBehaviour
{
void Start()
{
Cat cat = new Cat("小野猫");
Animal mouseA = new Mouse("mouseA", cat);
Animal mouseB = new Mouse("mouseB", cat);
Animal mouseC = new Mouse("mouseC", cat);
Animal mouseD = new Mouse("mouseD", cat);
Animal mouseE = new Mouse("mouseE", cat);
cat.Coming(/*mouseA, mouseB, mouseC, mouseD*/);
}
}
| 工厂模式
分类:
简单工厂模式
属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族种最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
特点:只生产一种品牌(类型)的产品,在工厂种动态创建
简单工厂模式推荐阅读:C#设计模式(1)——简单工厂模式 - Frank_520 - 博客园
图解:
SampleFactor:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Factor
{
public class SampleFactor
{
public AbstructMouse CreateMouse(MouseType emMouseType)
{
AbstructMouse mouse = null;
switch (emMouseType)
{
case MouseType.HpMouse:
mouse = new HpMouse();
break;
case MouseType.DellMouse:
mouse = new DellMouse();
break;
default:
break;
}
return mouse;
}
}
}
HpMouse:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Factor
{
public class HpMouse : AbstructMouse
{
public override void Print()
{
Debug.Log("生产了一个Hp鼠标");
}
}
}
DellMouse:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//using Factor;
namespace Factor
{
public class DellMouse : /*Factor.*/ AbstructMouse
{
public override void Print()
{
Debug.Log("生产了一个Dell鼠标");
}
}
}
AbstructMouse:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Factor
{
public abstract class AbstructMouse
{
public abstract void Print();
}
}
FactorMain:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public enum MouseType
{
None,
DellMouse,
HpMouse,
}
public class FactorMain : MonoBehaviour
{
void Start()
{
//RunNormal();
RunSampleFactor();
}
void RunNormal()
{
DellMouse dellMouse = new DellMouse();
dellMouse.Print();
HpMouse hpMouse = new HpMouse();
hpMouse.Print();
}
void RunSampleFactor()
{
SampleFactor factor = new SampleFactor();
AbstructMouse dellMouse = factor.CreateMouse(MouseType.DellMouse);
dellMouse.Print();
AbstructMouse hpMouse = factor.CreateMouse(MouseType.HpMouse);
hpMouse.Print();
}
void RunFactor()
{
}
void Update()
{
}
}
工厂模式
避免简单工厂模式种,新增产品品牌(类型)时,直接修改工厂类。为了解决这个问题出现了 工厂模式。
特点:只生产一种品牌(类型)的产品,在具体的子类工厂中创建。为了解决系列产品的问题,就有了抽象工厂模式。
工厂模式推荐阅读:C#设计模式(2)——工厂模式 - Frank_520 - 博客园
图解:
FactorBase:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Factor
{
public abstract class FactorBase
{
public abstract AbstructMouse CreateMouse();
}
}
DellFactor:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public class DellFactor : FactorBase
{
public override AbstructMouse CreateMouse()
{
return new DellMouse();
}
}
HpFactor:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public class HpFactor : FactorBase
{
public override AbstructMouse CreateMouse()
{
return new HpMouse();
}
}
AppleFactor:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public class AppleFactor : FactorBase
{
public override AbstructMouse CreateMouse()
{
return new AppleMouse();
}
}
FactorMain:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public class FactorMain : MonoBehaviour
{
void Start()
{
//RunNormal();
//RunSampleFactor();
RunFactor();
}
void RunFactor()
{
DellFactor dellFactor = new DellFactor();
AbstructMouse dellMouse = dellFactor.CreateMouse();
dellMouse.Print();
HpFactor hpFactor = new HpFactor();
AbstructMouse hpMouse = hpFactor.CreateMouse();
hpMouse.Print();
AppleFactor appleFactor = new AppleFactor();
AbstructMouse appleMouse = appleFactor.CreateMouse();
appleMouse.Print();
}
}
抽象工厂模式
为了解决系列产品的问题,就有了抽象工厂模式。
特点:抽象工厂可以生产多种产品。而简单工厂 / 工厂模式 只生产一种产品
抽象工厂模式推荐阅读:C#设计模式(3)——抽象工厂模式 - Frank_520 - 博客园
图解:
AbstructKeyBoard:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public abstract class AbstructKeyBoard
{
public abstract void Print();
}
AppleKeyboard / DellKeyboard / HpKeyboard :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public class AppleKeyboard : AbstructKeyBoard // 其他两个同理
{
public override void Print()
{
Debug.Log("Apple键盘");
}
}
AbstructFactor_Base:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public abstract class AbstructFactor_Base
{
public abstract AbstructMouse CreateMouse();
public abstract AbstructKeyBoard CreateKeyBoard();
}
AbstructFactor_Apple / AbstructFactor_Dell / AbstructFactor_Hp:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public class AbstructFactor_Apple : AbstructFactor_Base // 其他两个同理
{
public override AbstructKeyBoard CreateKeyBoard()
{
return new AppleKeyboard();
}
public override AbstructMouse CreateMouse()
{
return new AppleMouse();
}
}
FactorMain:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Factor;
public class FactorMain : MonoBehaviour
{
void Start()
{
//RunNormal();
//RunSampleFactor();
//RunFactor();
RunAbstructFactor();
}
void RunAbstructFactor()
{
AbstructFactor_Apple apple = new AbstructFactor_Apple();
AbstructMouse appleMouse = apple.CreateMouse();
appleMouse.Print();
AbstructKeyBoard appleKeyBoard = apple.CreateKeyBoard();
appleKeyBoard.Print();
Debug.Log("------------------------------------------");
AbstructFactor_Dell dell = new AbstructFactor_Dell();
AbstructMouse dellMouse = dell.CreateMouse();
dellMouse.Print();
AbstructKeyBoard dellKeyBoard = dell.CreateKeyBoard();
dellKeyBoard.Print();
Debug.Log("------------------------------------------");
AbstructFactor_Hp hp = new AbstructFactor_Hp();
AbstructMouse hpMouse = hp.CreateMouse();
hpMouse.Print();
AbstructKeyBoard hpKeyBoard = hp.CreateKeyBoard();
hpKeyBoard.Print();
}
}
| 适配模式
问题:Android / iOS 充电线标准不一样,只有一根线时,如何完成不同型号手机充电?
解决:适配器模式
适配模式推荐阅读: C#设计模式(7)——适配器模式 - Frank_520 - 博客园
图解:
Adaptor:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Adaptor
{
public enum AdaptorType
{
None,
Android,
iOS,
}
public interface IAdaptor
{
/// <summary>
/// 统一调用接口,大一统
/// </summary>
/// <param name="adaptorType"></param>
void Charge(AdaptorType adaptorType);
}
public class Adaptor : IAdaptor
{
// 之前已经写了非常多的代码,但是 现在需要增加一个转换器的接口
// 接口 用于拓展原始类不足的功能
AndroidLine androidLine = new AndroidLine();
IosLine iosLine = new IosLine();
public void Charge(AdaptorType adaptorType)
{
if (adaptorType == AdaptorType.Android)
androidLine.AndroidCharge();
else if (adaptorType == AdaptorType.iOS)
iosLine.IOSCharge();
}
}
}
IosLine:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Adaptor
{
public class IosLine
{
public void IOSCharge()
{
Debug.Log("借助iOS充电线充电中...");
}
}
}
AndroidLine:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Adaptor
{
public class AndroidLine
{
public void AndroidCharge()
{
Debug.Log("借助Android充电线充电中...");
}
}
}
AdaptorMain:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Adaptor
{
public class AdaptorMain : MonoBehaviour
{
void Start()
{
IAdaptor adaptor = new Adaptor();
adaptor.Charge(AdaptorType.Android);
adaptor.Charge(AdaptorType.iOS);
}
}
}