学习笔记总结

多态是什么?
同一个事件不同的做法, 目标一致,实现是多变的
为什么需要多态?
同一个方法对于子类会有不同的实现,关注行为的变化

如何体现多态?
将变化的行为封装后形成抽象,将具体实现推迟到子类。

多态常见语法形式?
父类引用子类对象
方法重载
方法重写
方法隐藏


父类的成员在子类不适用,解决方式有两个,1.方法隐藏,2.方法重写


不适用
1.子类不需要. 解决:重新审查父类的设计,遵循类的单一职责
2.子类需要,但做法不同  解决:修改  1) 隐藏,2)重写

方法隐藏(替换)
是多态的一种体现,解决父类的方法在子类不适用的问题,但解决方案不够彻底,
因为方法隐藏后如果通过子类调用子类对象的方法时,调用的是新方法,
如果父类引用调用子类对象,调用的还是从父类继承的方法。

注意:方法隐藏只能隐藏实现的方法
总结:调用隐藏方法调哪一个取决于引用的类型

方法隐藏的性能相比方法重写性能较优
方法隐藏是静态绑定的。一个类型的引用调用父类还是子类对象的方法时,是在编译期间就明确的。
所以调用避免了动态选择的问题,所以在运行期没有性能损失

方法重写(改写)
是多态的一种体现,解决父类的方法在子类不适用的问题,重写后的方法是在原方法表中修改记录,
所以不管父类引用,还是子类引用,调用的都是对象重写后的方法

注意:只有三类方法可重写,分别是abstract virtual override,子类重写父类方法时,必须加override关键字
总结:调用重写方法调哪一个取决于对象的类型

方法重写是动态绑定的。一个类型的引用调用父类还是子类对象的方法时,是由创建的对象决定的,
对象是运行期间创建的,所以方法的选择是在运行期完成的,性能相比方法隐藏较差

*******************************************************************************************************************************
接口

目标
理解接口
一组对外行为的规范。只关注行为,不关注数据,且不关注行为的实现
接口自身表达了“CAN Do”,不表达“How To”
接口与实现类
    一个类可以实现多个接口,多个接口间用","分隔
    一个类既继承父类又实现接口,先继承后实现,语法体现":"后先写类名,“,”分隔后写接口名
    实现类必须实现接口中定义的所有成员
    实现成员时不能加override ,但可以实现成为虚成员,也可以实现成为抽象成员
    语义:
    实现类与接口之间表达了“Like a”的关系,行为上可能一致,概念不同
接口与接口的继承
一个接口可以继承多个其它接口,即,接口是多继承的.


接口的显式实现
作用:
1.解决多接口实现成员二义性
2.接口中的成员在实现类不适用


做法:
在实现接口中定义的成员时加上接口的名称
    显式实现后该成员在本类中私有.
    通过本类对象无象在类外访问,通过接口类型引用调用
  
Freamwork中常用的接口
IComparable
IComparer
IEnumerable


抽象类与接口的区别
    语法:
抽象类:用abstract修饰,可以包含抽象与非抽象两种成员,
 派生类以重写的方式实现抽象成员,不能创建对象
    接口:用interface声明,只包含抽象(没有实现) 的成员,不能包含字段
  接口中的所有成员在派生类必须全部实现,不用override。不能创建对象
  类与类的继承是单继承,接口与接口的继承是多继承,
  一个类只能继承一个父类,但是可以实现多个接口
语义:
抽象类:表达一个抽象概念,是概念的抽象,派生类与抽象类表达"Is a"关系,耦合度较高
自上而下使概念形成一致
接口: 表达一组行为的抽象,是行为的抽象,实现类与接口表达"Like a"关系,耦合度较继承松散
                自下而下使行为形成一致



什么时候使用接口 : 统一多个类型的行为时

接口隔离
尽量写小接口,实现类需要更多的功能,则实现多个接口,
如果实现需要较少的功能,可以实现单个接口
面向接口编程,而非面向实现
设计一个类,首先思考该类对外提供什么能力,而不是去思考这个能力怎么实现
     
**************************************************************************
委托与事件       
题外话:<编程机制探析>

什么是委托
委托是方法的代理,委托是一种数据类型(引用), 委托是一个方法的别名
委托是一类行为的抽象

委托的使用
三步曲:
1.定义委托
public delegate int Handler(int index);
2.创建对象
//方式一:传统
Handler handler = new Handler(Fun);
//方式二:简化  方式一、二适合于用已有方法为委托赋值
Handler handler = Fun;
//方式三:匿名方法  适合于没有已声明方法,且当前方法不需要在其它地方调用
Handler handler = delegate(int index)
{
//方法实现
Console.WriteLine(index);
return index;
};
//方式四:Lambda表达式 适合于没有已方法,且方法极简单,简单到1到2行代码
=>(gose to)
Handler handler = index =>index*index; 
3.调用委托
handler();
委托的作用:
可以将方法做为参数传递
可以实现回调(call back) 
可以实现方法的异步调用

委托的分类
    单播委托:一个委托对象委托一个方法
多播委托:一个委托对象委托多个方法

委托的异步调用
方法的异步调用指方法不排队的调用,后一个方法不必等待前一个方法执行结束就可以开始调用
.Net Freamwork中所有的方法都可以异步调用,
实现方式是,将原有方法交由委托BeginInvoke开启异步调用
开启异步后,程序会单独开一个线程来执行当前需要异步调用的方法
如果异步调用的方法有返回值时,
一般会在异步结束时的回调方法中通过调用委托的EndInvoke取得返回值
具体实现参见课堂案例


委托与接口
在以下情况下,请使用委托:
1.当使用事件设计模式时。
2.当封装静态方法可取时。
3.当调用方不需要访问实现该方法的对象中的其他属性、方法或接口时。
4.需要方便的组合。
5.当类可能需要该方法的多个实现时。

在以下情况下,请使用接口:
1.当存在一组可能被调用的相关方法时。
    2.当类只需要方法的单个实现时。
3.当使用接口的类想要将该接口强制转换为其他接口或类类型时。
4.当正在实现的方法链接到类的类型或标识时:例如比较方法

事件模型(天然的观察者模式实现)
    


***********************************************************************************************************************************
集合,泛型,泛型集合

集合:一种数据容器,一种数据结构。
集合两大体系:非泛型,泛型

非泛型的缺点:
1.性能不好,因为可能发生装箱
2.类型不安全, 可能会发生类型转换的异常
3.使用不方便,用的时候需要手动做类型转换

非泛型集合:命名空间 System.Collections     泛型


列表: ArrayList List<T>
字典: Hashtable Dictionary<Tkey,TValue>
栈:    Stack Stack<T>
队列: Queue Queue<T>
链表: LinkedList
哈希集                                                        Hashset
有序的键/值对 SortedDictionary<TKey,TValue>
可定制排序方式的键/值对 SortedList<TKey,TValue>

泛型:
优点: 
某算法或数据结构可以基于类型不同而复用
类型安全,具有类型检查
性能较好,避免了装拆箱
使用方便,避免类型转换


约束

说明

T:struct
类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。 有关更多信息,请参见 使用可以为 null 的类型(C# 编程指南)。

T:class
类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。

T:new()
类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时, new() 约束必须最后指定。

T:<基类名>
类型参数必须是指定的基类或派生自指定的基类。

T:<接口名称>
类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。

T:U
为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。

**********************************************************************************************************************************************
结构,静态,泛型集合

结构与类的不同
结构中的构造方法中,必须为所有数据成员赋值,static或const除外
结构不能声明默认构造函数(没有参数的构造函数)或析构函数。
结构在赋值时进行复制。将结构赋值给新变量时,将复制所有数据,并且对新副本所做的任何修改不会更改原始副本的数据。在使用值类型的集合(如 Dictionary<string, myStruct>)时,请务必记住这一点。
结构是值类型,而类是引用类型。
与类不同,结构的实例化可以不使用 new 运算符。
结构可以声明带参数的构造函数。
一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。
结构可以实现接口。
结构可用作可以为 null 的类型,因而可向其赋 null 值。


静态
    语法:
    静态成员属于本类,不属于对象,但对象可以共享静态成员
    静态成员在在类加载时进入内存,且常驻内存,直到应用程序结束
    静态方法中只能访问本类静态成员,不能访问本类实例成员
    静态构造方法作用专用于静态成员初始化
    静态成员只能通过类访问
    静态成员不能继承
    
    语义:
    静态可以表达中立
    静态可以表达多对象的共享成员
    静态可以表达全局


    静态类
    静态类中只能包含静态成员
    静态类不能创建对象
    静态类不能继承
    静态类不能实现接口

List常用方法

增加 Add AddRange Insert 
删除 Remove RemoveAt RemoveRange RemoveAll
查找 IndexOf(T) LastIndexOf(T) Contains(T) 
  Find FindLast FindAll FindIndex FindLastIndex
  Exists

排序 Sort OrderBy OrderByDescending 
访问 this[int index] GetRange Foreach Select
 
*******************************************************************************************************************************************************
正则表达式与文件

正则表达式作用:
处理文本数据
验证
查找
替换

正则表式语言元素
字符类
\w   与任意有效单词字符匹配  如 : 字母,数字,下划线,中文单字
\d    与任意一个十进制数字   0-9
\s    与一个空白字符匹配   
[ ]   与括号中出现的任意一个字符匹配
[^ ] 与除括号中出现的所有字符匹配     
\b    与单词边界匹配    
.   与任意一个字符匹配


    定位符
^ 行首    
$   行尾

限定符 限定前一位字符出现的数量

*    0.....n
+    1.....n
?    0.....1
{n}  恰好n个
{n,m} 至少n个,最多m个
{n,}    至少n个, 最多不限
    
分组
()
(?<name> )

 *******************************************************************************************************************************

 IO 与 文件
 文件目录支持相应类
DriveInfo
Directory 
DirectoryInfo
File
FileInfo

流操作相应类
Stream
FileStream
MemoryStream
NetworkStream


****************************************************************************************************************************************************

 程序集与反射

反射的价值
为静态语言增加了动态功能

反射的作用:
(1) 查看类型信息
(2) 动态调用(动态创建对象,动态访问对象的成员)

反射时常用的类型
System.Type 类
System.Activator  类
System.Reflection  命名空间
类型
FieldInfo  字段
常用的方法 : SetValue GetValue
PropetyInfo 属性
   常用的方法 : SetValue GetValue
MethodInfo 方法
EventInfo 事件
ConstructInfo  构造方法
Assembly        程序集


反射时的常见使用流程
 1.得到类型 Type
 2.创建对象,访问成员
 3.对成员赋值,取值,对方法动态调用


反射常见应用
1.动态创建对象
2.做插件
3.代码热更新


如何得到Type对象
        //方式一 typeof(Person)  适用性:已知类型
        //方式二 p.GetType()      适用性:已知对象
        //方式三 Type.GetType("Person") 适用性:已知类型名称


动态创建对象
        //方式一: Activator.CreateInstance
        //方式二: Assembly.Load("XXX").CreateInstance();
//方式三: type.GetContruct().Invoke(); 


**********************************************************************************************************************************************************************************
异常,多线程,协程

异常

什么是异常
异常是运行时错误

使用异常处理的情况
1.外部资源(必须)
2.当通过决断避免的代码太复杂,且发生错误的可能性较低,
  此时用异常做事后处理是一种简单高效的做法

如何处理 
try{  //放可能会发生异常的代码}
catch(异常类型1 引用名)
{
//处理方式
//1.报告错误(面向用户)
//2.记录错误(面向开发者)
//3.向上抛出(面向代码)
}
catch(){} .....
finally
{
//资源释放 
}


可能会遇到的面试题
1. .net怎么做异常处理    A: try{}   catch(){} finally{}
2. try块中包含return 语句,finally还执行吗?  A:一定执行,执行完finally再返回



线程 
CPU处理数据的最小单元
进程 
在内存运行,并具有独立应用程序域的工作单元


应用程序(软件)
一个软件中可能包含多个进程。


进程与线程的关系
一个进程可能包含多个线程
操作系统中用进程来管理任务
CPU处理线程


如何开启一个新线程
创建System.Threading.Thread 类的对象,就表示创建一个线程


线程的同步-------面试题
    为什么需要线程同步的原因?
    线程的异步特性意味着必须协调对资源(如文件句柄、网络连接和内存)的访问。
否则,两个或更多的线程可能在同一时间访问相同的资源,
而每个线程都不知道其他线程的操作。结果将产生不可预知的数据损坏。


怎么实现线程同步? 加锁(独占)
当一个线程取得共享资源后,加锁保持当前线程独占访问,其他线程如想取得该资源,
只能等待当前线程释放该资源后,所以多个线程在访问共享资源时,是以排队方式访问,故称
之为线程同步(排队)


线程同步的代码实现 lock语句


lock(引用型对象)
{
//要锁定的代码
}

线程适用性
1.耗时较久方法调用      如:下载资源
2.长时间占用CPU运算  如:A*算法寻路计算

前台线程与后台线程
前台线程决定进程的存活,即,在进程中如果还有一个前台线程在工作,则进程不会结束
后台线程不决定进程的存活,即,在进程中如果没有工作的前台线程,
即使还有工作的后台线程,当最后一个前台线程结束时,所有的后台线程也随之结束

thread.IsBackground = true;

协程
0  null
WaitForEndOfFrame 等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前
WaitForSeconds 在给定的秒数内,暂停协同程序的执行
WaitForFixedUpdate   等待直到下一个固定帧速率更新函数
www 等待直到www从Url取得资源后再执行


**********************************************************************************************************************************************************************************
OO原则与设计模式


面向对象宏观思想
分而治之
高内聚,低耦合


切分,抽象时找变化
不变的永远是变化

原则
架构方面
开-闭原则
对扩展开放,对修改关闭
类的设计
类的单一职责
一个有且只有一个改变它的原因
面向接口编程,而非面向实现
设计一个类时,先思考该对外提供什么行为,而不去思考该行为如何实现
类的关系
里氏替换
父类出现的地方可以用子类替换,替换后父类原有的功能仍然正常使用
优先选择组合,而非继承
代码复用,能组合复用,不继承
依赖倒置 --依赖抽象,而非依赖实现
抽象的是稳定,而实现多变,
接口隔离
定义接口时,尽量细化,实现类可以组合实现,得到多个功能,实现类也可以挑选实现
类的交互
迪米特法则
类与类交互知道对方的信息越少越好


分析问题的思路
1.寻找变化点
2.抽象变化点
3.依赖抽象


什么是模式
      每一个模式描述了一个在我们周围不断重复发生的问题,
 以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动


三类设计模式
创建型 : 关注对象创建问题
单例模式: 问题:如何让一个类只创建一个对象或创建指定数量的对象  关键词:唯一对象
简单工厂: 问题:如何在多个类型中选择某一个来创建对象(多选一) 关键词:多选一
意图:声明一个创建子类产品对象的类,让该类决定实例化哪一个类的对象
效果:将创建与表示(使用)分离,
对象的创建工作交由工厂负责,客户代码只关注自身业务,职责单一化,
工厂在客户与产品间建立一个联系,工厂可看做是产品的代理。
客户需要产品时,找工厂创建
    
抽象工厂:问题:如何在多个类型中按照系列化创建类型对象(多选多)  关键词:系列
   意图:提供一个创建一系列相关或相互依赖的接口,而无需指定他们具体的类
        声明一个创建具体产品对象的类---工厂,在工厂中提供创建系列对象的接口(方法),
根据业务划分产品有多个种类,如玩家,场景,装备......, 但每种产品可能会有多个系列,
在对具体产品类选择上往往需要以系列化的方式来选择。因此需要实现多类型中按系列选择
多个具体产品类来创建相应对象. 
典型设计:在抽象工厂中只声明创建接口(方法),但无法实现,具体产品创建推迟到
具体系列工厂中实现.
用技术改善设计:用配置文件+反射将抽象工厂简化,去除具体工厂


如:以数据存储为例,对玩家,场景,装备信息访问可以有XML或SQL 存储方式,
xml,和SQL 就是系列化数据访问方案。 所以如果用XML系列的玩家数据访问类,则
一定也会使用XML系列的场景数据访问类.


适用性:见《设计模式》58页
1.需要客户代码只使用对象,不需要关心对象的创建时 。创建与表示分离


生成器:问题:对复杂对象中各部件的创建是可变化的。关键字:部件创建
适用性 : 见《设计模式》


结构型: 关注类或对象结构的组织


适配器:问题:将两个因为接口不同而不能直接交互的类,通过一个适配器(转换器)将接口转为
客户所希望的样子,从而实现对原有功能的复用  关键词:转换接口
别名:包装器


组合 :  问题:将对象组织为树形结构,方便层次化访问。对叶结点与枝结点统一处理  关键词:树


装饰器: 问题:动态扩展已有对象的行为,每装饰一次,对象行为增强一次. 关键词:包装行为

外观:为子系统中的一组接口提供一个一致的界面, facade模式定义了一个高层接口,
这个接口使得这一子系统更加容易使用  关键字:向导


行为型:关注对象间的交互问题
    模板方法 : 问题:执行步骤可变化,但执行流程(骨架)不变,
  因此在抽象层先定义好骨架,将步骤细节推迟到子类去实现  关键词:骨架


观察者: 问题:一个对象的改变同时需要通知更多的对象来响应   关键字:通知
状态:   允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
 关键字: 状态决定行为

策略:   定义一系列的算法 ,把它们一个个封装起来 ,  并且使它们可相互替换。本模式使得算法可独
立于使用它的客户而变化    关键字: 算法的选择



UpLoadSocre(userid,taskid,exp,score);

if(GetUserInfoByUserid(userid) != null user.Enable = true)
{
if(GetTaskInfo(taskid,userid) !=null)
{
if(exp> oldexp || score >oldscore)
{
Update(userid,task,exp,score);
}
else
{
player.exp += exp;
}
}
else
{
insert(userid,taskid,exp,score);
}
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值