一个精彩的Unity3d开发者必备之几种植设计模式

以同事和恋人等的印象中,张浩是一个憨厚、敦厚的青年,他工作扎扎实实勤奋,悉心指导学生,醉心学术研讨,生活休闲,家庭和睦,是一个典型的华儒。

Unity脚本编程

分明,unity的编程属于脚本化,脚本没有一个切实的概念和架构,
导致在路进程中,经常出现哪里需要贯彻啊效力,就不管添加脚本,
结果,就招致了同片烂,不好管理。

更有甚者,自己的描摹的代码闲置一段时间后,再失思找有功能的贯彻,都设以视图中再三找半龙。
哎!请或我于这个感叹一望,这还是若勾勒的东头西么?起名 1
因此,一个吓的设计模式是多的根本呀,

2015年5月16日,我校精密仪器与单电子工程学院教授张浩于过去美到国际会议途中被捕,目前给圈于圣何塞监,面临着经济间谍等罪的控诉。同时深受起诉的另外5人数受到,还有我校教师庞慰、陈津平。在美方对张浩等六叫中国国民的控中,以及美国主流媒体之报导备受,多次提及天津大学并意指学校有不当得利表现。学校对其他无端的弹射和加害学校声誉的所作所为与肯定声讨,并保留下法律手段维护校誉的权利。

安勾勒脚论架构

这就是说,我们以采取unity3d开发东西的时刻,脚本架构到底该什么来写?
呵呵…

实际,我啊给莫了你们切实答案,因为每个人之开销习惯,每个团队的出模式为各出千秋,
so,在是我偏偏开几栽设计模式的总,

信任大家已经通过各种渠道知道了自我之先生张浩先生的悲惨遭遇。欲加之罪,何患无辞,请大家相信张浩先生是无辜的。作为他的妻,最近直接在为外的工作四处奔走,内心中折磨。但是看到大家这么关注他、支持外,我恳切地表示感激。在此地自己表示张浩先生及其亲属,向你们说声:谢谢!

参照书籍

要参考书籍有《设计模式》《设计模式之禅》《大话设计模式》以及网上有零星的篇章,
但最主要内容或自己本身的一些经历和清醒。
形容出来的目的一方面是系统地收拾一下,一方面也跟广大的网友享受,
关于你们到底怎样使用,
望君斟酌啊!起名 2

天津大学

设计模式

设计模式对编程人员来说,的确很关键。
理所当然,如果大家之知情与自身有所不同,欢迎留言,大家共探讨。

  • 法1:单一任务
  • 极2:里氏替换原则(子类扩展但未改父类功能)
  • 规范3:依赖倒置原则
  • 条件4:接口隔离原则
  • 原则5:迪米特法则(最少知道原则)
  • 规格6:开闭原则

    规格1:单一任务规范

    说到纯任务规范,很多人数都见面瞧不起。
    以它们最好简单了,稍有经验的程序员即使从不曾读了设计模式、从来没听说过单一任务规范,在规划软件时也会见自觉的遵从就等同根本尺度,因为这是常识。
    于软件编程中,谁吗不愿意以修改了一个成效造成其他的功力产生故障。
    若是避免出现这等同题材之方法就是随单一任务规范。
    虽然单一任务规范如此简约,并且为当是常识,但是即使是经验丰富的程序员写起的顺序,也会见来违这无异规范的代码是。
    干什么会现出这种景象吧?因为起职责扩散。所谓职责扩散,就是以某种原因,职责为分化成了重周密的任务。

    ### 就此一个看似描述动物呼吸这个现象

    class Animal
    {
    
        public void breathe(string animal)
        {
            Debug.Log(animal + "呼吸空气");
        }
    }
    
    public class Client
    {
        Animal animal = new Animal();
    
        void Start()
        {
    
            animal.breathe("牛");
            animal.breathe("羊");
            animal.breathe("猪");
        }
    }
    
    //运行结果:
        //牛呼吸空气
        //羊呼吸空气
        //猪呼吸空气
    

    ### 当需求变动

    次第上线后,发现问题了,并无是享有的动物都呼吸空气的,比如鱼就是呼吸水的。

    修改时一旦以单一任务规范,需要拿Animal类细分为陆生动物类Terrestrial,水生动物Aquatic,代码如下:

    class Terrestrial
    {
        public void breathe(String animal)
        {
            Debug.Log(animal + "呼吸空气");
        }
    }
    
    class Aquatic
    {
        public void breathe(String animal)
        {
            Debug.Log(animal + "呼吸水");
        }
    }
    
    public class Client
    {
        public static void main(String[] args)
        {
            Terrestrial terrestrial = new Terrestrial();
            terrestrial.breathe("牛");
            terrestrial.breathe("羊");
            terrestrial.breathe("猪");
    
            Aquatic aquatic = new Aquatic();
            aquatic.breathe("鱼");
        }
    }
    
    //运行结果:
        //牛呼吸空气
        //羊呼吸空气
        //猪呼吸空气
        //鱼呼吸水
    

    ### 改动量小之道

    咱会意识要如此改资费是颇可怜的,除了用原来的近乎分解之外,还得修改客户端。
    如直接修改类Animal来上目的则违背了纯任务规范,但花费也多少的大半,代码如下:

    class Animal
    {
        public void breathe(String animal)
        {
            if ("鱼" == animal)
            {
                Debug.Log((animal + "呼吸水"));
            }
            else
            {
                Debug.Log((animal + "呼吸空气"));
            }
        }
    }
    
    public class Client
    {
        public static void main(String[] args)
        {
            Animal animal = new Animal();
            animal.breathe("牛");
            animal.breathe("羊");
            animal.breathe("猪");
            animal.breathe("鱼");
        }
    }
    

    ### 隐患

    足见见,这种修改章程使简单的基本上。
    不过却是在隐患:有同一龙要以鱼分为呼吸淡水之鱼群与呼吸海度的鱼类,
    虽同时欲修改Animal类的breathe方法,而针对原来代码的修改会对调用“猪”“牛”“羊”等息息相关力量带来风险,
    也许有同龙若晤面发现程序运行的结果变成“牛呼吸水”了。
    这种修改章程直接当代码级别达到背了单纯性任务规范,虽然改起来最好简便易行,但隐患也是不过特别之。

    ### 另一样栽修改章程

    class Animal
    {
        public void breathe(String animal)
        {
            Debug.Log(animal + "呼吸空气");
        }
    
        public void breathe2(String animal)
        {
            Debug.Log(animal + "呼吸水");
        }
    }
    
    public class Client
    {
        public static void main(String[] args)
        {
            Animal animal = new Animal();
            animal.breathe("牛");
            animal.breathe("羊");
            animal.breathe("猪");
            animal.breathe2("鱼");
        }
    }
    

    可以看,这种修改章程没有转原来的措施,而是在接近吃新加了一个办法,这样虽也背了纯粹任务规范,
    然于章程级别达到却是入单一任务规范的,因为其并不曾动原来方式的代码。这三种方式各发生优缺点,
    那么在实质上编程中,采用哪一中呢?
    实际这的确比难说,需要根据实际情况来规定。
    我的规格是:只有逻辑足够简单,才可以在代码级别达到背单一任务规范;只有类中方法数量足够少,才足以当艺术级别及负单一任务规范。

    ### 遵循单一职责原的独到之处有

  • 足降低类的复杂度,一个像样才当同项任务,其逻辑肯定要比负责多宗任务简单的大半;

  • 增进类的可读性,提高系统的可维护性;

  • 转引起的高风险降低,变越必然的,如果单纯任务规范遵循的好,当修改一个成效时,可以判下跌对另外功能的影响。

    内需验证的某些是纯任务规范不只是面向对象编程思想所特有的,只要是模块化的次序设计,都适用单一任务规范。

    法2:里氏替换原则

    ### 名字的由

    自然有成百上千人数以及自身正好看这项条件的时光同样,对这个规格的讳充满疑惑。
    骨子里原因即是这项条件最早是以1988年,由麻省理工学院之同一号姓里的妇人(Barbara
    Liskov)提出来的。
    简单易行的话吧,就是当我们采用持续时,遵循里氏替换原则。

    ### 定义

    流淌:类B继承类A时,除补偿加新的方就新增功外,尽量不要还写父类A的法,也硬着头皮不要重载父类A的道。
    继往开来包含这样平等叠含义:父类中凡是已经实现好的艺术(相对于肤浅方法而言),实际上是当设定一文山会海的正规化以及契约,
    尽管它不强制要求有所的子类必须遵这些契约,但是倘若子类对这些不抽象方法任意修改,
    就会针对周继承体系造成破坏。而里氏替换原则就是是发挥了立无异于重合含义。
    持续作为面向对象三坏特点有,在叫程序设计带来巨大便利的而,也带了弊端。
    依使持续会于程序带来侵入性,程序的可移植性降低,增加了目标中的耦合性,如果一个像样吃其他的类所继承,
    则当以此类似需要修改时,必须考虑到具备的子类,并且父类修改后,
    有着关乎到子类的法力都产生或会见发生故障。

    ### 继承的高风险

    那即便吃咱一道看继承的高风险,如下:

    class A
    {
        public int func1(int a, int b)
        {
            return a - b;
        }
    }
    
    public class Client
    {
        void Start()
        {
            A a = new A();
            Debug.Log("100-50=" + a.func1(100, 50));
            Debug.Log("100-80=" + a.func1(100, 80));
        }
    }
    

    #### 运行结果

    100-50=50
    100-80=20

    ### 需求变动

    后来,我们需要追加一个新的功效:完成两频相加,然后再次与100告与,由类B来顶住。
    即类B需要形成两单力量:
    区区再三相减。
    星星屡次相加,然后还加100。
    由类A已经实现了第一只力量,所以类B继承类A后,只需要更好第二独效益就可以了,代码如下

    class B:A
    {
        public int func1(int a, int b)
        {
            return a + b;
        }
    
        public int func2(int a, int b)
        {
            return func1(a, b) + 100;
        }
    }
    
    public class Client
    {
        private void Start()
        {
            B b = new B();
            Debug.Log("100-50=" + b.func1(100, 50));
            Debug.Log("100-80=" + b.func1(100, 80));
            Debug.Log("100+20+100=" + b.func2(100, 20));
        }
    }
    

    #### 类B运行结果

    100-50=150
    100-80=180
    100+20+100=220

    ### 影响了正规的功用

    俺们发现原运行正常化的相减功能来了不当。
    故即是类B在为方从名时无意中再写了父类的点子,造成所有运行相减功能的代码全部调用了类B重写后的章程,造成原本运行如常的成效出现了不当。
    以本例中,引用基类A完成的效益,换成子类B之后,发生了要命。
    当其实编程中,我们经常会透过重新写父类的不二法门来形成新的功用,这样勾画起虽然简易,
    可整个继承体系之而复用性会比较不同,特别是采取多态比较频繁时,程序运行出错的几带队十分非常。
    要无要是又写父类的法,比较通用的做法是:原来的父类和子类都连续一个重通俗的基类,原有的累关系去丢,采用依赖、聚合,组合等事关代替。

    ### 里氏替换原则通俗的来讲就是是

    子类可以扩大父类的效用,但非克更改父类原有的功用。它含有以下4层意思:
    1.子好像可实现父类的抽象方法,但切莫可知遮住父类的非抽象方法。
    2.子近似吃得以多自己有意的方。
    3.当子类的道重载父类的计时,方法的放开条件(即方法的形参)要比较父类方法的输入参数还宽大。
    4.当子类的方式实现父类的悬空方法时,方法的后置条件(即方法的返回值)要较父类更严峻。

看上去很不可思议,因为我们会发现在自己编程中常常会违反里氏替换原则,程序照样跑的好好的。  
所以大家都会产生这样的疑问,假如我非要不遵循里氏替换原则会有什么后果?  
后果就是:你写的代码出问题的几率将会大大增加。

**原则3:依赖倒置原则**
-----------------------

### 定义

高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。

以抽象为基础搭建起来的架构比以细节为基础搭建起来的架构要稳定的多。  
抽象指的是接口或者抽象类,细节就是具体的实现类,使用接口或者抽象类的目的是制定好规范和契约,而不去涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成。

### 依赖倒置原则核心思想

依赖倒置原则的核心思想是面向接口编程,我们依旧用一个例子来说明面向接口编程比相对于面向实现编程好在什么地方。

### 情景举例

场景是这样的,母亲给孩子讲故事,只要给她一本书,她就可以照着书给孩子讲故事了。代码如下:

    class Book
    {
        public String getContent()
        {
            return "很久很久以前有一个阿拉伯的故事……";
        }
    }

    class Mother
    {
        public void narrate(Book book)
        {
            Debug.Log("妈妈开始讲故事");
            Debug.Log(book.getContent());
        }
    }

    public class Client
    {
        void Start()
        {
            Mother mother = new Mother();
            mother.narrate(new Book());
        }
    }

#### 运行结果:

妈妈开始讲故事  
很久很久以前有一个阿拉伯的故事……

### 需求变动

运行良好,假如有一天,需求变成这样:不是给书而是给一份报纸,让这位母亲讲一下报纸上的故事,报纸的代码如下:

    class Newspaper
    {
        public String getContent()
        {
            return "林书豪38+7领导尼克斯击败湖人……";
        }
    }

这位母亲却办不到,因为她居然不会读报纸上的故事,这太荒唐了,只是将书换成报纸,居然必须要修改Mother才能读。  
假如以后需求换成杂志呢?换成网页呢?  
还要不断地修改Mother,这显然不是好的设计。  
原因就是Mother与Book之间的耦合性太高了,必须降低他们之间的耦合度才行。

### 抽象的接口

我们引入一个抽象的接口IReader。  
读物,只要是带字的都属于读物:

    interface IReader
    {
        String getContent();
    }

Mother类与接口IReader发生依赖关系,而Book和Newspaper都属于读物的范畴,  
他们各自都去实现IReader接口,这样就符合依赖倒置原则了,代码修改为:

    interface IReader
    {
        String getContent();
    }

    class Newspaper : IReader
    {
        public String getContent()
        {
            return "林书豪17+9助尼克斯击败老鹰……";
        }
    }
    class Book : IReader
    {
        public String getContent()
        {
            return "很久很久以前有一个阿拉伯的故事……";
        }
    }

    class Mother
    {
        public void narrate(IReader reader)
        {
            Debug.Log("妈妈开始讲故事");
            Debug.Log(reader.getContent());
        }
    }

    public class Client
    {
        public static void main(String[] args)
        {
            Mother mother = new Mother();
            mother.narrate(new Book());
            mother.narrate(new Newspaper());
        }
    }

#### *运行结果*

*妈妈开始讲故事  
很久很久以前有一个阿拉伯的故事……  
妈妈开始讲故事  
林书豪17+9助尼克斯击败老鹰……*


这样修改后,无论以后怎样扩展Client类,都不需要再修改Mother类了。  
这只是一个简单的例子,实际情况中,代表高层模块的Mother类将负责完成主要的业务逻辑,一旦需要对它进行修改,引入错误的风险极大。  
所以遵循依赖倒置原则可以降低类之间的耦合性,提高系统的稳定性,降低修改程序造成的风险。  
采用依赖倒置原则给多人并行开发带来了极大的便利,


比如上例中,原本Mother类与Book类直接耦合时,Mother类必须等Book类编码完成后才可以进行编码,因为Mother类依赖于Book类。  
修改后的程序则可以同时开工,互不影响,因为Mother与Book类一点关系也没有。  
参与协作开发的人越多、项目越庞大,采用依赖导致原则的意义就越重大。  
现在很流行的TDD开发模式就是依赖倒置原则最成功的应用。

### 在实际编程中,我们一般需要做到如下3点

1.低层模块尽量都要有抽象类或接口,或者两者都有。  
2.变量的声明类型尽量是抽象类或接口。使用继承时遵循里氏替换原则。  
3.依赖倒置原则的核心就是要我们面向接口编程,理解了面向接口编程,也就理解了依赖倒置。

原则4:接口隔离原则
-------------------

### 定义

客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。  
将臃肿的接口I拆分为独立的几个接口,类A和类C分别与他们需要的接口建立依赖关系。也就是采用接口隔离原则。  
举例来说明接口隔离原则:

### 未遵循接口隔离原则的设计

[![](https://images0.cnblogs.com/blog/363476/201502/121642263862512.jpg)](https://images0.cnblogs.com/blog/363476/201502/121642244953356.jpg)   
这个图的意思是:类A依赖接口I中的方法1、方法2、方法3,类B是对类A依赖的实现。  
类C依赖接口I中的方法1、方法4、方法5,类D是对类C依赖的实现。  
对于类B和类D来说,虽然他们都存在着用不到的方法(也就是图中红色字体标记的方法),但由于实现了接口I,所以也必须要实现这些用不到的方法。

### 示例代码

对类图不熟悉的可以参照程序代码来理解,代码如下:

    //接口
    interface I
    {
        void method1();
        void method2();
        void method3();
        void method4();
        void method5();
    }

    class A
    {
        public void depend1(I i)
        {
            i.method1();
        }
        public void depend2(I i)
        {
            i.method2();
        }
        public void depend3(I i)
        {
            i.method3();
        }
    }

    class B : I
    {
        public void method1()
        {
            Debug.Log("类B实现接口I的方法1");
        }
        public void method2()
        {
            Debug.Log("类B实现接口I的方法2");
        }
        public void method3()
        {
            Debug.Log("类B实现接口I的方法3");
        }
        //对于类B来说,method4和method5不是必需的,但是由于接口A中有这两个方法,
        //所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。
        public void method4() { }
        public void method5() { }
    }

    class C
    {
        public void depend1(I i)
        {
            i.method1();
        }
        public void depend2(I i)
        {
            i.method4();
        }
        public void depend3(I i)
        {
            i.method5();
        }
    }

    class D : I
    {
        public void method1()
        {
            Debug.Log("类D实现接口I的方法1");
        }
        //对于类D来说,method2和method3不是必需的,但是由于接口A中有这两个方法,
        //所以在实现过程中即使这两个方法的方法体为空,也要将这两个没有作用的方法进行实现。
        public void method2() { }
        public void method3() { }

        public void method4()
        {
            Debug.Log("类D实现接口I的方法4");
        }
        public void method5()
        {
            Debug.Log("类D实现接口I的方法5");
        }
    }

    public class Client
    {
        void Start()
        {
            A a = new A();
            a.depend1(new B());
           a.depend2(new B());
           a.depend3(new B());

            C c = new C();
          c.depend1(new D()));
            c.depend2(new D());
            c.depend3(new D());
        }
    }

可以看到,如果接口过于臃肿,只要接口中出现的方法,不管对依赖于它的类有没有用处,实现类中都必须去实现这些方法,这显然不是好的设计。  
如果将这个设计修改为符合接口隔离原则,就必须对接口I进行拆分。

### 遵循接口隔离原则的设计

在这里我们将原有的接口I拆分为三个接口,拆分后的设计如图2所示:

[![](https://images0.cnblogs.com/blog/363476/201502/121642286981139.jpg)](https://images0.cnblogs.com/blog/363476/201502/121642275421825.jpg)

### 示例代码

照例贴出程序的代码,供不熟悉类图的朋友参考:

    interface I1
    {
         void method1();
    }

    interface I2
    {
         void method2();
         void method3();
    }

    interface I3
    {
         void method4();
         void method5();
    }

    class A
    {
        public void depend1(I1 i)
        {
            i.method1();
        }
        public void depend2(I2 i)
        {
            i.method2();
        }
        public void depend3(I2 i)
        {
            i.method3();
        }
    }

    class B : I1, I2
    {
        public void method1()
        {
            Debug.Log("类B实现接口I1的方法1");
        }
        public void method2()
        {
            Debug.Log("类B实现接口I2的方法2");
        }
        public void method3()
        {
            Debug.Log("类B实现接口I2的方法3");
        }
    }

    class C
    {
        public void depend1(I1 i)
        {
            i.method1();
        }
        public void depend2(I3 i)
        {
            i.method4();
        }
        public void depend3(I3 i)
        {
            i.method5();
        }
    }

    class D : I1, I3
    {
        public void method1()
        {
            Debug.Log("类D实现接口I1的方法1");
        }
        public void method4()
        {
            Debug.Log("类D实现接口I3的方法4");
        }
        public void method5()
        {
            Debug.Log("类D实现接口I3的方法5");
        }
    }

接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。  
也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。  
本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。


在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。  
接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。  
说到这里,很多人会觉的接口隔离原则跟之前的单一职责原则很相似,其实不然。  
其一,单一职责原则原注重的是职责;而接口隔离原则注重对接口依赖的隔离。  
其二,单一职责原则主要是约束类,其次才是接口和方法,它针对的是程序中的实现和细节;

而接口隔离原则主要约束接口,主要针对抽象,针对程序整体框架的构建。

### 注意几点

采用接口隔离原则对接口进行约束时,要注意以下几点:  
1.接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。  
2.为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。  
3.提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。  
运用接口隔离原则,一定要适度,接口设计的过大或过小都不好。设计接口的时候,只有多花些时间去思考和筹划,才能准确地实践这一原则。

 

原则5:迪米特法则
-----------------

### 定义

**一个对象应该对其他对象保持最少的了解**  
类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。  
因此,尽量降低类与类之间的耦合。  
自从我们接触编程开始,就知道了软件编程的总的原则:低耦合,高内聚。  
无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。  
低耦合的优点不言而喻,但是怎么样编程才能做到低耦合呢?那正是迪米特法则要去完成的。

### 最少知道原则

迪米特法则又叫最少知道原则,最早是在1987年由美国Northeastern
University的Ian Holland提出。  
通俗的来讲,就是一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。  
迪米特法则还有一个更简单的定义:只与直接的朋友通信。首先来解释一下什么是直接的朋友:  
每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。  
耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,  
而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。

### 违反迪米特法则的设计

举一个例子:有一个集团公司,下属单位有分公司和直属部门,现在要求打印出所有下属单位的员工ID。  
先来看一下违反迪米特法则的设计。

    //总公司员工
    class Employee
    {
        private String id;
        public void setId(String id)
        {
            this.id = id;
        }
        public String getId()
        {
            return id;
        }
    }

    //分公司员工
    class SubEmployee
    {
        private String id;
        public void setId(String id)
        {
            this.id = id;
        }
        public String getId()
        {
            return id;
        }
    }

    class SubCompanyManager
    {
        public List<SubEmployee> getAllEmployee()
        {
            List<SubEmployee> list = new List<SubEmployee>();
            for (int i = 0; i < 100; i++)
            {
                SubEmployee emp = new SubEmployee();
                //为分公司人员按顺序分配一个ID
                emp.setId("分公司" + i);
                list.Add(emp);
            }
            return list;
        }
    }

    class CompanyManager
    {

        public List<Employee> getAllEmployee()
        {
            List<Employee> list = new List<Employee>();
            for (int i = 0; i < 30; i++)
            {
                Employee emp = new Employee();
                //为总公司人员按顺序分配一个ID
                emp.setId("总公司" + i);
                list.Add(emp);
            }
            return list;
        }

        public void printAllEmployee(SubCompanyManager sub)
        {
            List<SubEmployee> list1 = sub.getAllEmployee();
            foreach (SubEmployee e in list1)
            {
                Debug.Log(e.getId());
            }


            List<Employee> list2 = this.getAllEmployee();
            foreach (Employee e in list2)
            {
                Debug.Log(e.getId());
            }
        }
    }

    public class Client
    {
        void Start()
        {
            CompanyManager e = new CompanyManager();
            e.printAllEmployee(new SubCompanyManager());
        }
    }

现在这个设计的主要问题出在CompanyManager中,根据迪米特法则,只与直接的朋友发生通信,  
而SubEmployee类并不是CompanyManager类的直接朋友(以局部变量出现的耦合不属于直接朋友),从逻辑上讲总公司只与他的分公司耦合就行了,  
与分公司的员工并没有任何联系,这样设计显然是增加了不必要的耦合。

### 修改后的代码

按照迪米特法则,应该避免类中出现这样非直接朋友关系的耦合。修改后的代码如下:

    class SubCompanyManager
    {
        public List<SubEmployee> getAllEmployee()
        {
            List<SubEmployee> list = new List<SubEmployee>();
            for (int i = 0; i < 100; i++)
            {
                SubEmployee emp = new SubEmployee();
                //为分公司人员按顺序分配一个ID
                emp.setId("分公司" + i);
                list.Add(emp);
            }
            return list;
        }
        public void printEmployee()
        {
            List<SubEmployee> list = this.getAllEmployee();
            foreach (SubEmployee e in list)
            {
                Debug.Log(e.getId());
            }
        }
    }

    class CompanyManager
    {
        public List<Employee> getAllEmployee()
        {
            List<Employee> list = new List<Employee>();
            for (int i = 0; i < 30; i++)
            {
                Employee emp = new Employee();
                //为总公司人员按顺序分配一个ID
                emp.setId("总公司" + i);
                list.Add(emp);
            }
            return list;
        }

        public void printAllEmployee(SubCompanyManager sub)
        {
            sub.printEmployee();
            List<Employee> list2 = this.getAllEmployee();
            foreach (Employee e in list2)
            {
                Debug.Log(e.getId());
            }
        }
    }

### 主要的变化

[![](https://images0.cnblogs.com/blog/363476/201502/121653292296877.png)](https://images0.cnblogs.com/blog/363476/201502/121653282293049.png)

修改后,为分公司增加了打印人员ID的方法,总公司直接调用来打印,从而避免了与分公司的员工发生耦合。

### 总结

迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。  
但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,  
总公司就是通过分公司这个“中介”来与分公司的员工发生联系的。  
过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。  
所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。

 

原则6:开闭原则
---------------

### 定义

**一个软件实体如类、模块和函数应该对扩展开放,对修改关闭**

在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,  
可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。  
因此,当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。  
闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统。开闭原则可能是设计模式六项原则中定义最模糊的一个了,

它只告诉我们对扩展开放,对修改关闭,可是到底如何才能做到对扩展开放,对修改关闭,并没有明确的告诉我们。  
以前,如果有人告诉我“你进行设计的时候一定要遵守开闭原则”,我会觉的他什么都没说,但貌似又什么都说了。因为开闭原则真的太虚了。  
在仔细思考以及仔细阅读很多设计模式的文章后,终于对开闭原则有了一点认识。  
其实,我们遵循设计模式前面5大原则,以及使用23种设计模式的目的就是遵循开闭原则。

### 如何遵守

也就是说,只要我们对前面5项原则遵守的好了,设计出的软件自然是符合开闭原则的,这个开闭原则更像是前面五项原则遵守程度的“平均得分”,  
前面5项原则遵守的好,平均分自然就高,说明软件设计开闭原则遵守的好;  
如果前面5项原则遵守的不好,则说明开闭原则遵守的不好。  
其实,开闭原则无非就是想表达这样一层意思:用抽象构建框架,用实现扩展细节。  
因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。  
而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了。  
当然前提是我们的抽象要合理,要对需求的变更有前瞻性和预见性才行。

 

**如何去遵守这六个原则**
------------------------

对这六个原则的遵守并不是
**是和否**的问题,而是**多和少**的问题,也就是说,我们一般不会说有没有遵守,而是说遵守程度的多少。  
任何事都是过犹不及,设计模式的六个设计原则也是一样,制定这六个原则的目的并不是要我们刻板的遵守他们,而需要根据实际情况灵活运用。  
对他们的遵守程度只要在一个合理的范围内,就算是良好的设计。  
如果大家对这六项原则的理解跟我有所不同,欢迎指正![](http://www.unitymanual.com/static/image/smiley/default/20119000.gif)

### 说明

本文转载自并对其整理目录[:\[ζއ随风去旅行\] Unity3d
一个优秀的程序必备的几种设计模式](http://www.unitymanual.com/thread-22531-1-1.html)

张浩的夫人:范莉萍

2015年6月5日

各位老师、同学、朋友等:

天津大学授予师生校友捐款倡议书

校方同时披露了“来自张浩妻子的求救”和“捐款倡议书”。在求助信中张浩妻子表示,一旦案件进入司法程序,要拿走胜诉,好之律师是赢的重中之重。但“大之律师事务所的报价在2000万顶3500万人民币内,作为一个习以为常的家园,我们无力承受这么高昂的律师费。“由此,天津大学工会和学友总会向全体师生员工及校友发了通向张浩妻子的捐款倡议。

天津大学声明

6月3日,张浩在美国的家里范莉萍女士发来了求助函。她当信中感谢学校、学院与热心的冤家等针对家人的看管,特别感谢北美硅谷校友会第一时间去看望张浩,并感谢学校及各方校友积极行动,帮助寻找和推介律师。但是它对于连续的案子被面临的经济窘迫表达了深刻的忧患,并公开求助于师生及校友,希望收获大家之帮带。

识张浩先生的人,一定记得他那淳朴的、腼腆的笑容。他是自从乡下出来的贫穷子弟,靠在和谐的穿梭大力,赴美留学、工作,最后抱揣在当一号称老师的巴,毅然来到御好教书,建设MEMS实验室。我们是湖南总人口,在天津孤身一人,有时候自己耶会见埋怨,但他连笑笑说,自己喜爱本之状态,天好的学童好聪明伶俐,素质特别强,他专程好当此处当教师和举行科研的感觉到。他意味着以融洽善于的领域做和好善于的政工,特别开心。就是这样同样称作单纯的科研工作者,从未在重点起诉地工作存过,竟让FBI和美国司法部门恶意诬告成经济间谍及商业间谍。

咱俩用持续密切关注气象发展,并当必要时使用更为的行以维护学校声誉和职工的正当权益。

6月1日,当儿女辈沉浸在儿童节的开心中时时,张浩也以美国第一破开庭,每次听到儿子,透过微信,奶声奶气地边叫边寻找“爸爸”时,我就算克制不住地泪如雨下。我努力告诉要好,不要哭,要坚强,老公是无罪的,一定要是吃他找到最好的律师,还他天真。在美国,一旦案件进入司法程序,只有依靠张浩先生与律师之通力合作才能够从赢官司,取得胜诉,好之辩护律师是取胜的严重性。但美国底律师费非常贵,大之律师事务所的报价在2000万暨3500万人民币内,作为一个屡见不鲜的家中,我们无力负担这么高昂的律师费,为了保卫我们天津大学讲师以及校的名气,希望各位导师、同学、朋友等会奉献有同客爱心,声援并支持张先生由赢就会官司。

自一如泣如诉专案

2015年6月5日

不过,张浩时恰为圈于美国圣何塞监狱,面临着经济间谍等罪行的指控。按照美国法例,张浩必须找到合适的律师团体,才生或就此法律手段维护自己之回旋,证明自己的纯洁。然而美国高昂的律师费用,对于生于农村的便工薪家庭来说,无疑是天文数字。

美国加州北区联邦法院出具的诉讼相关文书。

张浩2009年来校任教,是同名为优秀的青年教师。他本次在得意被捕,面临多码指控,他得用法律武器保护个人权益、证明自己清白;然而,他出身农村起名,家境平凡,很有或为经济由错过法律维权的会。因此,天津大学声称,将全力支持张浩的律维权行动!同时也要全球有良知的师等,热爱正义和真理的各界人士,共同支持和拉我们的行进。

天津大学工会

2015年6月3日

星期一开庭,我算看出了张浩先生。在庭上,他隔三差五用眼神远远地安慰自己,但自身实在不敢多看他几目,我看无异不好哭一不好,直到外被捎。看正在他戴在手铐给带,我之胸臆还碎了,霎时泪如泉涌。那会儿,我们都未明了张浩先生深受控诉了哪些罪名,直到后来在辩护人那儿看到起诉书。张先生让控30桩罪名,如果罪名成立,刑期将大及10年及15年。

张浩妻子范莉萍求助信

你们好!

天津大学全体师生、校友:

也诚恳期待社会及之热心人士也克伸出援手,帮助张浩同家属共度难关。

为此,天津大学工会暨同学总会特向全体师生员工和同学发倡议,恳请每位天大师生和同班,能够伸出援手,尽好能力,为以美国看守所中之张浩争取一个验证自己纯洁的时机;为张浩的2秋小争取一个暨上下相聚的机遇。

并且深受起诉的六称呼涉案中国人民被,除张浩外,还连该同学的先生庞慰、陈津平。昨日,天津大学通过网站、微信及微博公号发出声明,对美方指控中及美国主流媒体报道中“任何无端的指责以及摧残学校声誉的行为”予以明确谴责,并保留下法律手段维护维护校誉的权利。

天津大学校友总会

天津大学是华夏第一所现代高校,已生120年之办学史。在遥远的办学进程遭到,形成了“实事求是”的校训和“严谨治学”的校风,在国内外具有美好的学术声望。学校高度重视学术道德建设,鼓励师生在遵循法律规定与学术规范之前提下,自由探索未知世界,不断开创文明硕果,服务社会,造福人类。

5月16日,我校精仪学院教授张浩在去美到学术会议的行程中,被美国围捕并拘留。消息传回,广大师生和同班都多震惊。

工作发生之后,天津大学北美硅谷校友分会之同桌第一时间看望了张浩,学校、张浩所以学院的有关官员、课题组得同事等看看了张浩的大,张浩先生的学习者等、校友等、还有许多各级面的意中人提供了大量之律师事务所信息,张浩与本身本着大家的眷顾表示诚心地感谢。

当年凡自及张浩先生结婚的第十个新春,我们发出个少于载的宜人儿子,是单常见的老三总人口底寒。张浩先生是独独立的科研工作者,不擅言辞、不懂应酬,但可勤奋好学、刻苦钻研,经常工作到夜里11碰才回家。他的生存概括到除了工作就是门。工作之衍,他无限开心之从事便是陪伴儿子共同玩。我们叫儿从名笑笑,就是要他会乐地健康长大。一家人之光阴大概温馨,可不幸就这么不期而到了。

我们感到痛心,我们发气愤,我们是冤枉的,我们是无罪的!为了保个人清白和天津大学之世纪名气,我们自然要是与FBI抗争到底!

5月16日,天津大学精密仪器与光电子工程学院教授张浩于应邀前往美国凤凰城到国际微波会议时,在洛杉矶国际机场入境时被捕。张浩时给拘留于圣何塞监狱,并坐涉及经济间谍罪而备受起诉。

校一直秉承开放包容之国际化办学理念,高度重视人才建设,坚持聘用世界名牌的世学者与漂亮留学人员来校担任教职,鼓励师生进行大的学术交流活动。早在1895年建校前制定的率先统大学章程中就是明确提出:“头等学堂,以选延教习、挑取学生两充分捧最为根本”。建校之始,学校虽请毕业为美国达特茅斯大学跟欧柏林学院的丁家立先生担任第一管总教习(执行校长),长齐11年的永。时至今日,重视人才、尊重人才、爱护人才、善待人才已经成为学校的相同种植知识习惯。

5月16日,当机下滑于洛杉矶机场,美国联邦调查局(以下简称FBI)的彪形大汉们将张浩先生与本身分别携了,在浑浑噩噩的搜和了解后,我吃放飞了。当时脑子里只有发一样词话,“你生曾经于通缉并拘留在监狱被,目前立马宗事是保密的,指控将当周一法庭上让公布。”傍晚,我一个人口,谁呢未认识,孤零零地在机场,哀求着一样对准境内来之父子并住宿。他是独热心人,尽管他国内的家跟朋友还认为自己是骗子,可他于闻我和亲人呼天抢地的讲后,最终成为了第一个帮扶我的口。在大酒店发生了网络下,我起来联络家属、校方、大使馆和张浩先生在美国之校友,大家都感觉异常吃惊、很陡。这么一个善良、和蔼、腼腆的人头,怎么会让FBI带走吧?

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图