合理地分布类中的代码。顺序为:公有静态变量、私有静态变量、公有普通变量、私有普通变量、公共函数、私有函数。
尽可能地保持类的封装。尽可能使函数或变量保持私有,不对外暴露太多细节。
类应该短小,短小是指尽量保持单一权责原则。类或模块应有且只有一条加以修改的理由。
合理提高类的内聚性。我们希望类的内聚性保持在较高的水平。内聚性高,表示类中方法和变量相互依赖,相互结合成一个逻辑整体。
有效地隔离修改。类应该依赖于抽象,而不是依赖于具体细节。尽量对设计解耦,做好系统中的元素的相互隔离,做到更加灵活与可复用。
像报纸一样一目了然。名称应该简单并一目了然,源文件顶部应该给出高层次概念和算法,细节应该往下渐次展开,直到找到源文件中最底层的函数和细节。
恰如其分的注释。带少量注释的整洁而有力的代码,比带有大量注释的零碎而复杂的代码更加优秀。
单文件行数不要太长,尽可能几百行以内。
合理利用空白行。命名空间、类、函数之间,都用空白行隔开。
让紧密相关的代码互相靠近。
基于关联的代码分布:变量声明靠近使用位置、实体变量在类的顶部声明、函数调用者放在被调用函数的上面
团队应该遵循一套代码规范。
短小。最好将单个函数控制在10行以内。
单一职责。函数应该只做一件事情。只做一件事,做好这件事。
具描述性的名称。长而具有描述性的名称,比短而费解的名称好。当然,如果函数在已经足够说明问题,还是越短越好。
参数尽可能少。最理想的函数参数形态是零参数,其次是单参数,再次是双参数,应尽量避免三参数及以上参数的函数,有足够的理由才能用三个以上参数。
尽力避免重复。重复的代码会导致模块的臃肿,整个模块的可读性可能会应该重复的消除而得到提升。
要名副其实,一个好的变量、函数或类的名称应该已经答复了所有的大问题。一个好的名称可以大概告诉你这个名称所代表的内容,为什么会存在,做了什么事情。应该如何用等。
要避免误导。我们应该避免留下隐藏代码本意的错误线索,也应该避免使用与本意相侼的词。
尽量做有意义的区分。尽量避免使用数字系列命名(a1、a2)和没有意义的区分。
尽量使用读得出来的名称。如名称读不出来,讨论的时候会不方便且很尴尬。
尽量使用可搜索的名称。名称长短应与其作用域大小相对应,若变量或常量可能在代码中多处使用,应赋予其以便于搜索的名称。
取名不要绕弯子。取名要直白,要直截了当,明确才是王道。
类名尽量使用名词。类名尽量使用名词或名词短语,最好不要是动词。
方法名尽量使用动词。方法名尽量使用动词或动词短语。
每个概念对应一词,并一以贯之。对于那些会用到你代码的程序员,以一贯之的命名法简直就是天降福音。
通俗易懂。应尽力写出易于理解的变量名,要把代码写得让他别然能一目了然,而不让人去非常费力地去揣摩其含义。
尽情使用解决方法领域专业术语。尽量去用那些计算机科学领域的专业术语、算法名、模块名、数学术语。
要添加有意义的语境。需要用有良好命名的类,函数或名称空间来放置名称,给读者提供语境。若没能提供放置的地方,还可以给名称添加前缀。
编写代码的难度,取决于周边代码的阅读难度。想要快速实现需求,想要快速完成任务,想要轻松的写代码,请先让你书写的代码整洁易读。
保持整洁的习惯,发现脏代码就要及时纠正,花时间保持代码整洁,这不但有关效率,还有关项目的生存。
程序员遵从不了解混乱风险的产品经理(策划)的意愿,都是不专业的做法。
让代码比你来时更干净:如果每次签入时,代码都比签出时干净,那么代码就不会腐化,
赶上期限的唯一方法,做的更快的唯一方法,就是始终尽可能保持代码的整洁。
不常用,一般的数组容器都会给定自己的迭代器,使用现成的就好了,一般不需要自己实现。
//抽象迭代器 public interface Iterator { object First(); object Next(); bool HasNext(); object Current(); }
//抽象容器 public interface Comtainer { void Add(object o); void Remove(object o); Iterator CreateInterator(); }
//具体迭代器 using System.Collections.Generic; public class AIterator : Iterator { private List<object> list; private int currentIndex = 0; public AIterator(List<object> l) { list = l; } public object Current() { return list[currentIndex]; } public object First() { if (list.Count > 0) { return list[0]; } return null; } public bool HasNext() { if (currentIndex >= list.Count) { return false; } return true; } public object Next() { object current = list[currentIndex]; currentIndex++; return current; } }
//具体容器 using System.Collections.Generic; public class AContainer : Comtainer { private List<object> list = new List<object>(); public void Add(object o) { list.Add(o); } public Iterator CreateInterator() { return new AIterator(list); } public void Remove(object o) { if (list.Contains(o)){ list.Remove(o); } } }
//测试使用 using UnityEngine; public class tsetInterator : MonoBehaviour { void Start () { Comtainer aContainer = new AContainer(); aContainer.Add(10); aContainer.Add(30); aContainer.Add(80); Iterator i = aContainer.CreateInterator(); while (i.HasNext()) { Debug.Log(i.Next()); } } }
就是为容器创建一个接口来创建迭代器,通过迭代器有访问遍历容器的数据的能力,记录当前位置等。
//基础玩家类 public interface BasePlayer { int GetHp(); }
//基础装饰类,同样是继承基础玩家类 public class BaseDecorator : BasePlayer { private BasePlayer player; public BaseDecorator(BasePlayer b) { player = b; } public virtual int GetHp() { return player.GetHp(); } }
public class APlayer : BasePlayer { public int GetHp() { return 200; } }
public class KuziDress:BaseDecorator { public KuziDress(BasePlayer b) : base(b) { } public override int GetHp() { //穿上裤子装备后的血量 return base.GetHp() + 100; } }
public class YiFuDress : BaseDecorator { public YiFuDress(BasePlayer b) : base(b) { } public override int GetHp() { return base.GetHp() + 50; } }
using UnityEngine; public class testDress : MonoBehaviour { void Start () { BasePlayer player = new APlayer(); player = new KuziDress(player); player = new YiFuDress(player); Debug.Log(player.GetHp()); } }
如果装饰很多就需要创建很多很多的装饰类,而且,玩家Player他自己都不知道自己穿了多少个装饰。
//抽象类,公共接口 public interface Subject { void Request(); }
//真实对象,被代理对象 using UnityEngine; public class RealSubject : Subject { public void Request() { Debug.Log("do something"); } }
//代理者 using UnityEngine; public class Proxy : Subject { private Subject target; public Proxy(Subject s) { target = s; } public void Request() { Debug.Log("做事前"); target.Request(); Debug.Log("做事后"); } }
//测试 using UnityEngine; public class testProxy : MonoBehaviour { private void Start() { Subject subject = new Proxy(new RealSubject()); subject.Request(); } }
代理者可以在访问被代理之前和之后做一些操作。
一、接口类
public interface IDianYuan { string GiveDian(); }
二、原电源类,需要更改
public class AllDianYuan : IDianYuan { public string GiveDian() { return "220V"; } }
三、目标电源,需要更换上面的为这个
public class TargetDianYuan { //接口不一样 public string GiveDianYuan() { return "5V"; } }
四、适配者类
public class AdaptDianYuan : IDianYuan { private TargetDianYuan targetDianYuan = new TargetDianYuan(); public string GiveDian() { return targetDianYuan.GiveDianYuan(); } }
五、适配者使用
using UnityEngine; public class testAdapt : MonoBehaviour { void Start () { IDianYuan allDianYuan = new AllDianYuan(); Debug.Log(allDianYuan.GiveDian()); Debug.Log("要换 TargetDianYuan,但是接口不同"); //使用适配电源转换一下 allDianYuan = new AdaptDianYuan(); Debug.Log(allDianYuan .GiveDian()); } }
在原电源和目标电源都很难发生改变的时候,所以就是用一个适配者类来适用原来的接口再去调用目标电源。
发起者(需要保存状态的对象)-》创建备忘录给-》备忘录管理者保存
发起者(需要恢复状态的对象)=》通过备忘录管理者-》获取到指定的状态
//备忘录 using UnityEngine; public class Memento { private Vector3 saveV; private string name; public Memento(Vector3 v) { saveV = v; } public Vector3 GetData() { return saveV; } public void SetName(string n) { name = n; } }
//发起者 using UnityEngine; public class Player : MonoBehaviour { public void Set(Vector3 v) { this.transform.position = v; } public Memento SaveToMemento() { Debug.Log("保存当前位置"); return new Memento((Vector3)transform.position); } public void RestoreFromMemento(Memento m) { Debug.Log("恢复到位置:" + m.GetData()); transform.position = m.GetData(); } }
//备忘录管理者 using System.Collections.Generic; using UnityEngine; public class MementoManager { private Dictionary<string, Memento> dic = new Dictionary<string, Memento>(); public void AddMemento(string name,Memento m) { if (!dic.ContainsKey(name)) dic.Add(name, m); } public Memento GetMomento(string name) { if (dic.ContainsKey(name)) return dic[name]; return null; } }
//测试使用 using UnityEngine; public class testMemento : MonoBehaviour { void Start () { Player player = this.GetComponent<Player>(); MementoManager manager = new MementoManager(); manager.AddMemento("o",player.SaveToMemento()); player.Set(new Vector3(10, 3, 5)); player.RestoreFromMemento(manager.GetMomento("o")); } }