《大话设计模式》读书笔记
基础知识
1. 类是具有相同属性和功能对象的抽象的集合。
2. Public表示它所修饰的类成员可以调用。Protected表示他修饰的类成员只可以被子类调用,不能被外部类调用。而private表示他修饰的类成员不能被外部或子类调用
3. 属性有2个方法Get、Set。Get访问器返回与声明的属性相同的数据类型,表示的意思是调用的时候可以得到内部字段的值或者引用;set访问器没有显式设置参数,但有一个隐式参数value,它的作用是调用属性时可以给内部的字段和引用赋值。
4. 每个对象都包含它能进行操作所需要的全部信息,这个特性称为封装,因此对象不必依赖其它对象来完成自己的操作。
5. 封装能有很多好处。第一:良好的封装能够减少耦合。第二:类内部的实现可以自由的修改。第三:类具有清晰的对外接口。
6. 如果子类继承了父类,第一:子类拥有父类非private的属性和功能。第二:子类具有自己的属性和功能,即子类可以扩展父类没有的属性和功能。第三:子类可以以自己的方式实现父亲的功能(重写)
7. 对于父类的构造方法,子类不能继承,只能调用。如果要调用父类的成员,可以用base关键字。如Dog类调用父类Animal的构造方法:public dog():base (){}
8. 多态表示不同的对象可以执行相同的操作,但要通过它们自己的实现代码来执行。
9. 为了使子类的实例完全接替来自父类的类成员,父类必须将该成员声明为虚拟的。这是通过在该成员返回类型之前添加visual关键字来实现。然后,子类可以选择使用override关键字,将父类的实现替换为它自己的实现,这就是方法的重写Override, 或者叫做方法的覆写。
10. 多态的原理就是在方法被调用时,无论对象是否被转换成父类,都只有位于对象继承链最末端的方法实现会被调用。也就是说,虚方法是安装运行时类型而非编译时类型进行动态绑定调用的。
11. 使用抽象类必须注意的几点。第一:抽象类不能实例化。第二:抽象方法是必须被子类重写的方法。第三:如果类中包含抽象方法,那么类就必须被定义为抽象类,不论是否还包含其它一般方法。
12. 抽象类代表一个抽象的概念,他提供一个继承的出发点,当设计一个新的抽象类时,一定是用来继承的。所以,在一个继承关系形成的等级结构里面,树叶节点应该是具体类,而树枝节点均应该是抽象类。
13. 接口是把隐式的公共方法和属性组合起来,以封装特定功能的一个集合。一旦类实现了接口,类就可以支持接口所指定的所有属性和成员。声明接口在语法上与声明抽象类完全相同,但不允许提供接口中任何成员的执行方式。实现接口的类就必须实现接口的所有方法和属性,一个类可以支持多个接口,多个类也可以支持相同的接口。
14. 接口用interface声明,而不是class,接口名称前面要加”I”,接口方法或属性前面不能有修饰符,方法没有方法体。
15. 抽象类可以给出一些成员的实现,接口却不包含成员的实现,抽象类的抽象成员可以被子类部分实现,接口的成员需要类的完全实现,一个类只能继承一个抽象类,但可以实现多个接口。
16. 区分类和接口的三点:第一:类是对对象的抽象,抽象类是对类的抽象,接口是对行为的抽象。第二:如果行为跨越不同类的对象,可使用接口,对于一些相似的类对象,可以继承抽象类。第三:从设计的角度讲,抽象类是从子类中发现了公共的东西,泛化出父类,然后子类继承父类,而接口是根本就不知道子类的存在,方法如何实现还不确认,预先定义。
17. 所谓装箱就是把值类型打包到Object引用类型的一个实例中,所谓拆箱就是从对象中提取值类型。相对与简单的赋值而言,装箱拆箱需要大量的计算。对于值类型进行装箱时,必须分配并构造一个全新的对象。其次,拆箱索取的强制转换也需要大量的计算。
18. 泛型是具有占位符(类型参数)的类,结构,接口和方法。这些占位符是类,结构,接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符,类型参数作为其字段的类型和其方法的参数的类型出现。
19. 通常情况下,都建议使用泛型的集合,因为这样可以获得类型安全的直接有点而不需要从基集合类型派生并实现类型特定的成员。此外,如果集合元素为值类型,泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型集合类型派生的类型),因为使用泛型时不必对元素进行装箱。
20. 委托是对函数的封装,可以看作给方法的特征指定一个特殊的名称。而事件则是委托的一种特殊的形式,当发生有意义的事情的时候,事件对象通知处理过程。
21. 委托是一种引用方法的类型,一旦为委托分配了方法,委托将于该方法具有完全相同的的行为。委托用关键字delegate来声明,而事件是说在发生其他类或对象关注的事情时,类或对象可以通过事件来通知他们。
22. 注意委托的使用方法。
各种设计模式
1.简单工厂模式
1.将业务逻辑与界面逻辑分开,个人感觉此模式就是一个过渡模式,能用它解决的问题用工厂模式更好。以后也不会使用这种鸡肋的模式。此外讲到了UML:(图)
2.类图分为3层:第一层是类的名称;第二层是它的属性和字段;第三层是它的方法:其中+表示public,-表示private,#表示protected,它们后面的冒号表示类型
2.策略模式:
1.面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
2.策略模式的视图
3.策略模式是一种定义了一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
4.策略模式的strategy类层次为context定义了一系列可供重用的算法和行为。继承有助于析取这些算法的公共功能。
5.应用场景:只要在分析过程中听到需要在不同的时间应用不同的业务规则,就可以考虑使用策略模式来处理这种变化的可能性。
单一职责原则
1. 单一职责原则:就一个类而言,应该只有一个引起它变化的原因。
2. 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或抑制这个类完成其它职责的能力。这种耦合会导致错误的设计,当变化发生时,系统会遭到意想不到的破坏。软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。如过你能想到多于一个动机去修改那个类,那个类就多了一个职责。
开放-封闭原则
1. 无论模块多么封闭,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭作出选择。他必须猜测到最有可能发生变化的种类,然后构造出抽象来隔离这种变化。
依赖倒转原则
1. 原话解释是抽象不应该依赖于细节,而细节应该依赖与抽象。说白了就是针对接口编程而不是针对实现编程。
2. 里氏代换原则:一个软件实体如果使用的是一个父类的话,那么一定适用其子类,而且他察觉不出父类对象与子类对象的区别。也就是说,在软件里面,把父类都替换成子类,程序的行为没有变化。更通俗的将:子类必须能够替换掉它们的父类型。
3. 依赖倒转可以说是面向对象编程的标志,用哪种语言来编写程序并不重要,如果编写时考虑的是如何正对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者,那就是面向对象的设计,反之那就是过程化的设计了。
装饰模式
1. 装饰模式与建造者模式的组装都是应该在内部完成的,不同的是建造者模式的建造过程是稳定的,而装饰这是一个任意改变顺序。
2. 装饰模式动态的给一个对象增添了一个额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
1. 个人感觉装饰者模式就是一个逐层(从下到上)调用某个方法的模式,有些类似于“冒泡”。那个方法的特征就是函数体都有base.operation();
2. 装饰模式总结:装饰模式就是为已有的功能动态添加新的功能的一种方式。我以前的设计是当系统需要新功能的时候,是向旧的类中添加新的代码,这些新的代码通常装饰了原有类的核心职责或主要行为,在主类加入了新的字段,新的方法,新的逻辑,从而增加了主类的复杂度,而这些新加的东西仅仅是为了满足一些只有在某些特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放到一个单独的类中,并让这个类包装他所需要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择的,按顺序的执行装饰功能包装对象了。
3. 装饰模式的优点是把类中的装饰功能从类中搬移去除,这样可以简化原有的类。另外有效的把类的核心职责与装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
代理模式
1. 代理模式就是为其它对象提供一种代理以控制对这种对象的访问。
1. 代理模式的几种用途:第一,远程代理:就是为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在不同的地址空间的事实。第二,虚拟代理:根据需要创建开销很大的对象,通过 他来存放实例化需要很长时间的真实对象。第三是安全代理,用来控制真实对象访问时的权限。第四是智能指引,是用来调用真实的对象时,代理处理另外一些事。
工厂方法模式
1. 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是如果要加一种运算方法,那么就要在工厂类中修改判断逻辑,违背了修改关闭的原则,所以才需要工厂方法模式。但工厂方法模式的结构就显得臃肿一些了。(无奈~~~)
2. 工厂方法模式:定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。
1. 工厂方法模式实现时,客户端决定需要实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部判断逻辑移到了客户端代码来执行,你想要加功能,本来是要改工厂类的,而现在是修改客户端。
原型模式
1. 原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
1. 在.NET中实现ICloneable接口, Clone复制结构,而Copy连结构带内容一起复制。
2. MemberWiseClone是浅表复制,如果字段是值类型的,则对其进行逐位复制。如果是引用类型,则只复制引用而不复制引用的对象。
模版方法模式
1. 既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模板,所有重复的代码都要上升到父类去,而不是让每个子类都去重复。
2. 模板方法模式应用场景:当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现有可能不同时,我们通常要考虑用模板方法进行处理。
3. 模板方法模式:定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法结构就可以重新定义该算法的某些特定步骤。
5. 模板方法模式是通过把不变的行为搬到超类,去除子类中的重复代码来体现它的优势。
迪米特法则
1. 迪米特法则也叫最少知识法则。如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用。但是如果一个类需要调用另一个类的某个方法的话,就要通过第三者转发这个调用。
2. 在类的结构设计上,每一个类都要尽量降低成员的访问权限。迪米特法则的根本思想,就是强调了类之间的松耦合。我们在程序设计时,类之间的耦合越弱,越利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。
外观模式
1. 外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这一子系统更加容易使用。
3. 外观模式如何使用:首先,在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层,业务逻辑层和表示层的层与层之间建立外观Façade。其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂。大多数模式在使用时也会产生很多很小很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难。增加外观Façade可以提供一个简单的接口,减少它们之间的依赖。在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,可以为新系统开发一个外观Façade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Façade对象交互,Façade与遗留代码交互所有复杂的操作。
建造者模式
1. 建造者模式:将一个复杂对象的构建与它的表示分离开,使得同样的构建过程可以创建不同的表示。
3. 建造者模式应用场景:它主要用于创建复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临复杂的变化。所以说,建造者模式是在当创建复杂的对象的算法应该独立与该对象的的组成部分以及它们的装配方式时适用的模式。
观察者模式
1. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够更新自己。
3. 观察者模式应用场景:将一个系统分割成一系列相互作用的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望维护这个一致性而使各类耦合,这样会给维护,重用,和扩展带来不便。所以当一个对象改变同时会改变其它对象而且它不知道具体有多少对象有待改变,就应该考虑使用观察者模式。当一个抽象模型有两个方面,其中一个方面依赖与另外一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立的改变和复用。总的来讲,观察者模式所做的工作其实是在解除耦合,让耦合的双方都依赖与抽象,而不是依赖与具体,从而使得各自的变化都不会影响到另一边的变化。
4. 委托就是一种引用方法的类型。一旦为委托分配了方法,委托将于该方法具有完全相同的行为。委托方法的使用可以像其它任何方法一样,具有参数和返回值。委托可以看成是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。一个委托可以搭载多个方法,所有的方法被依次的唤起,更重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类。(可以转到客户端来定义观察者,减少了通知者与观察者的耦合)
抽象工厂模式
1. 抽象工厂模式:提供一个创建一系列相关或相互依赖的对象的接口,而无需指定它们具体的类。
3. 它的坏处体现在:如果要增加一个Project表,就要增加三个类,修改三个类才可以实现。这是可以考虑用简单工厂模式,在逻辑部分用分支条件判断语句。
4. 利用反射技术可以动态的实例化一个类。格式为Assembly.Load(“程序集名称”).CreateInstance(“命名空间名称.类名”);
状态模式
1. 状态模式的定义:当一个对象的内部状态改变时允许改变其行为,这个对象看起来像是改变了其类。
2. 状态模式的应用场景:状态模式主要解决的是当控制一个对象状态转换的条件过于复杂的情况。把状态判断的逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当一个对象的行为取决与它的状态,并且它必须在运行时刻根据它的状态来改变它的行为时,就可以考虑使用状态模式了。
4. 状态模式的好处是将于特定状态相关的行为局部化,并且将不同状态的行为分离开。目的是为了消除庞大的if语句,通过把各种状态转移逻辑分布到state的子类之间,来减少相互间的依赖。
适配器模式
1. 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
2. 适配器模式应用场景:系统的数据和行为都正确,但接口不符时,我们应该考虑使用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。 适配器模式主要是应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
4. 当双方都不太容易修改时才要用适配器。DataAdapter用作DataSet和数据源之间的适配器以便检索和保存数据。DataAdapter通过映射Fill(这更改了DataSet中的数据以便与数据源中的数据相匹配)和Update(修改了数据源中心的数据以便与DataSet中的数据想匹配)。
备忘录模式
1. 备忘录模式:在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样就可将该对象恢复到原先保存的状态。
组合模式
1. 将对象组合成树形结构以表示部分—整体的层次结构,组合模式使得用户对单个对象和对组合对象的使用具有一致性。
3. List<Component>也可以定义树形结构。
4. 组合模式使用场景:当发现需求中是体现部分与整体结构层次时,以及你希望用户可以忽略组合对象与单个对象的不同,统一使用组合结构的所有对象,就应该考虑使用组合模式了。
迭代器模式
1. 迭代器模式:提供一种方法顺序访问一个聚合对象的各个元素,而又不暴露该对象的内部表示。
2. 迭代器模式使用场景:当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就要用这个模式。
5. 在.NET中用foreach in 就可以了
单例模式
1. 单例模式定义:保证一个类只有一个实例,并提供一个访问它的全局访问点。
2. 通常我们可以让一个全局变量使得一个对象被访问,但他不能防止你实例化多个对象。一个最好的办法就是,让类自身负责维护它的唯一实例,这个类可以保证没有其它的实例可以被创建,并且它可以提供一个访问该实例的方法。
合成/聚合复用原则
1. 尽量使用合成/聚合,尽量不用类的继承。
2. 聚合表示一种弱的拥有关系,体现的是A对象可以包含B对象,而B对象不是A对象的一部分。合成是一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
3. 优先使用对象的合成/聚合将有助与你保持每个类被封装,并被集中到单个任务上,这样类和类继承层次会保持较小的规模,并且不太可能被继承为不可控制的庞然大物。
4. 将抽象部分与它的实现部分分离,使它们可以独立的变化。其中抽象与实现的分离是指抽象类和派生类用来实现自己的对象彼此独立。我的理解是实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
命令模式
1. 命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户
3. 命令模式的优点:第一,它能够很容易的设计出一个命令队列;第二,在需要的情况下,能够较容易的将命令记入日志;第三,允许接受的一方决定是否否决请求。第四,能够很容易的对请求进行撤销和重做;第五,由于加进新的具体类不影响其它的类,因此增加新的具体类很容易。总之,命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分离开。
职责链模式
1. 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传送该请求,直到有一个对象处理它为止。
3. 职责链的关键是当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandle对象负责处理它。这样使得接收者和发送者都没有对方的明确信息,且链中的对象自己也不知道链的结构,结果是职责链可简化对象间的相互连接,它们仅需要保持一个指向其后继者的引用,而不需要保持它所有的候选接受者的引用
中介者模式
1. 中介者模式:用一个中介者来封装一系列对象的交互。中介者使对象不需要显式的相互引用,从而使其耦合松散,而且可以独立改变它们之间的交互。
3. 中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合,以及想定制一个分布在多个类中的行为,而又不想生成太多子类的场合。
享元模式
1. 运用共享技术有效的支持大量细粒度的对象。
3. 享元模式的应用场景:如果一个应用 程序使用了大量的对象,而大量的对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以为外部状态,如果删除对象的外部状态,那就可以用较少的共享对象取代很多子对象,此时可以考虑使用享元模式。
访问者模式
1. 访问者模式表示一个作用于某对象结构中的各元素的操作。它使你可以考虑在不改变各元素类的前提下定义作用于这些元素的新操作。
基础知识
1. 类是具有相同属性和功能对象的抽象的集合。
2. Public表示它所修饰的类成员可以调用。Protected表示他修饰的类成员只可以被子类调用,不能被外部类调用。而private表示他修饰的类成员不能被外部或子类调用
3. 属性有2个方法Get、Set。Get访问器返回与声明的属性相同的数据类型,表示的意思是调用的时候可以得到内部字段的值或者引用;set访问器没有显式设置参数,但有一个隐式参数value,它的作用是调用属性时可以给内部的字段和引用赋值。
4. 每个对象都包含它能进行操作所需要的全部信息,这个特性称为封装,因此对象不必依赖其它对象来完成自己的操作。
5. 封装能有很多好处。第一:良好的封装能够减少耦合。第二:类内部的实现可以自由的修改。第三:类具有清晰的对外接口。
6. 如果子类继承了父类,第一:子类拥有父类非private的属性和功能。第二:子类具有自己的属性和功能,即子类可以扩展父类没有的属性和功能。第三:子类可以以自己的方式实现父亲的功能(重写)
7. 对于父类的构造方法,子类不能继承,只能调用。如果要调用父类的成员,可以用base关键字。如Dog类调用父类Animal的构造方法:public dog():base (){}
8. 多态表示不同的对象可以执行相同的操作,但要通过它们自己的实现代码来执行。
9. 为了使子类的实例完全接替来自父类的类成员,父类必须将该成员声明为虚拟的。这是通过在该成员返回类型之前添加visual关键字来实现。然后,子类可以选择使用override关键字,将父类的实现替换为它自己的实现,这就是方法的重写Override, 或者叫做方法的覆写。
10. 多态的原理就是在方法被调用时,无论对象是否被转换成父类,都只有位于对象继承链最末端的方法实现会被调用。也就是说,虚方法是安装运行时类型而非编译时类型进行动态绑定调用的。
11. 使用抽象类必须注意的几点。第一:抽象类不能实例化。第二:抽象方法是必须被子类重写的方法。第三:如果类中包含抽象方法,那么类就必须被定义为抽象类,不论是否还包含其它一般方法。
12. 抽象类代表一个抽象的概念,他提供一个继承的出发点,当设计一个新的抽象类时,一定是用来继承的。所以,在一个继承关系形成的等级结构里面,树叶节点应该是具体类,而树枝节点均应该是抽象类。
13. 接口是把隐式的公共方法和属性组合起来,以封装特定功能的一个集合。一旦类实现了接口,类就可以支持接口所指定的所有属性和成员。声明接口在语法上与声明抽象类完全相同,但不允许提供接口中任何成员的执行方式。实现接口的类就必须实现接口的所有方法和属性,一个类可以支持多个接口,多个类也可以支持相同的接口。
14. 接口用interface声明,而不是class,接口名称前面要加”I”,接口方法或属性前面不能有修饰符,方法没有方法体。
15. 抽象类可以给出一些成员的实现,接口却不包含成员的实现,抽象类的抽象成员可以被子类部分实现,接口的成员需要类的完全实现,一个类只能继承一个抽象类,但可以实现多个接口。
16. 区分类和接口的三点:第一:类是对对象的抽象,抽象类是对类的抽象,接口是对行为的抽象。第二:如果行为跨越不同类的对象,可使用接口,对于一些相似的类对象,可以继承抽象类。第三:从设计的角度讲,抽象类是从子类中发现了公共的东西,泛化出父类,然后子类继承父类,而接口是根本就不知道子类的存在,方法如何实现还不确认,预先定义。
17. 所谓装箱就是把值类型打包到Object引用类型的一个实例中,所谓拆箱就是从对象中提取值类型。相对与简单的赋值而言,装箱拆箱需要大量的计算。对于值类型进行装箱时,必须分配并构造一个全新的对象。其次,拆箱索取的强制转换也需要大量的计算。
18. 泛型是具有占位符(类型参数)的类,结构,接口和方法。这些占位符是类,结构,接口和方法所存储或使用的一个或多个类型的占位符。泛型集合类可以将类型参数用作它所存储的对象的类型的占位符,类型参数作为其字段的类型和其方法的参数的类型出现。
19. 通常情况下,都建议使用泛型的集合,因为这样可以获得类型安全的直接有点而不需要从基集合类型派生并实现类型特定的成员。此外,如果集合元素为值类型,泛型集合类型的性能通常优于对应的非泛型集合类型(并优于从非泛型集合类型派生的类型),因为使用泛型时不必对元素进行装箱。
20. 委托是对函数的封装,可以看作给方法的特征指定一个特殊的名称。而事件则是委托的一种特殊的形式,当发生有意义的事情的时候,事件对象通知处理过程。
21. 委托是一种引用方法的类型,一旦为委托分配了方法,委托将于该方法具有完全相同的的行为。委托用关键字delegate来声明,而事件是说在发生其他类或对象关注的事情时,类或对象可以通过事件来通知他们。
22. 注意委托的使用方法。
各种设计模式
1.简单工厂模式
1.将业务逻辑与界面逻辑分开,个人感觉此模式就是一个过渡模式,能用它解决的问题用工厂模式更好。以后也不会使用这种鸡肋的模式。此外讲到了UML:(图)
2.类图分为3层:第一层是类的名称;第二层是它的属性和字段;第三层是它的方法:其中+表示public,-表示private,#表示protected,它们后面的冒号表示类型
2.策略模式:
1.面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
2.策略模式的视图
3.策略模式是一种定义了一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
4.策略模式的strategy类层次为context定义了一系列可供重用的算法和行为。继承有助于析取这些算法的公共功能。
5.应用场景:只要在分析过程中听到需要在不同的时间应用不同的业务规则,就可以考虑使用策略模式来处理这种变化的可能性。
单一职责原则
1. 单一职责原则:就一个类而言,应该只有一个引起它变化的原因。
2. 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或抑制这个类完成其它职责的能力。这种耦合会导致错误的设计,当变化发生时,系统会遭到意想不到的破坏。软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。如过你能想到多于一个动机去修改那个类,那个类就多了一个职责。
开放-封闭原则
1. 无论模块多么封闭,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭作出选择。他必须猜测到最有可能发生变化的种类,然后构造出抽象来隔离这种变化。
依赖倒转原则
1. 原话解释是抽象不应该依赖于细节,而细节应该依赖与抽象。说白了就是针对接口编程而不是针对实现编程。
2. 里氏代换原则:一个软件实体如果使用的是一个父类的话,那么一定适用其子类,而且他察觉不出父类对象与子类对象的区别。也就是说,在软件里面,把父类都替换成子类,程序的行为没有变化。更通俗的将:子类必须能够替换掉它们的父类型。
3. 依赖倒转可以说是面向对象编程的标志,用哪种语言来编写程序并不重要,如果编写时考虑的是如何正对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者,那就是面向对象的设计,反之那就是过程化的设计了。
装饰模式
1. 装饰模式与建造者模式的组装都是应该在内部完成的,不同的是建造者模式的建造过程是稳定的,而装饰这是一个任意改变顺序。
2. 装饰模式动态的给一个对象增添了一个额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。
1. 个人感觉装饰者模式就是一个逐层(从下到上)调用某个方法的模式,有些类似于“冒泡”。那个方法的特征就是函数体都有base.operation();
2. 装饰模式总结:装饰模式就是为已有的功能动态添加新的功能的一种方式。我以前的设计是当系统需要新功能的时候,是向旧的类中添加新的代码,这些新的代码通常装饰了原有类的核心职责或主要行为,在主类加入了新的字段,新的方法,新的逻辑,从而增加了主类的复杂度,而这些新加的东西仅仅是为了满足一些只有在某些特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放到一个单独的类中,并让这个类包装他所需要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择的,按顺序的执行装饰功能包装对象了。
3. 装饰模式的优点是把类中的装饰功能从类中搬移去除,这样可以简化原有的类。另外有效的把类的核心职责与装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。
代理模式
1. 代理模式就是为其它对象提供一种代理以控制对这种对象的访问。
1. 代理模式的几种用途:第一,远程代理:就是为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在不同的地址空间的事实。第二,虚拟代理:根据需要创建开销很大的对象,通过 他来存放实例化需要很长时间的真实对象。第三是安全代理,用来控制真实对象访问时的权限。第四是智能指引,是用来调用真实的对象时,代理处理另外一些事。
工厂方法模式
1. 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是如果要加一种运算方法,那么就要在工厂类中修改判断逻辑,违背了修改关闭的原则,所以才需要工厂方法模式。但工厂方法模式的结构就显得臃肿一些了。(无奈~~~)
2. 工厂方法模式:定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。
1. 工厂方法模式实现时,客户端决定需要实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部判断逻辑移到了客户端代码来执行,你想要加功能,本来是要改工厂类的,而现在是修改客户端。
原型模式
1. 原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
1. 在.NET中实现ICloneable接口, Clone复制结构,而Copy连结构带内容一起复制。
2. MemberWiseClone是浅表复制,如果字段是值类型的,则对其进行逐位复制。如果是引用类型,则只复制引用而不复制引用的对象。
模版方法模式
1. 既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模板,所有重复的代码都要上升到父类去,而不是让每个子类都去重复。
2. 模板方法模式应用场景:当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现有可能不同时,我们通常要考虑用模板方法进行处理。
3. 模板方法模式:定义一个操作中算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法结构就可以重新定义该算法的某些特定步骤。
5. 模板方法模式是通过把不变的行为搬到超类,去除子类中的重复代码来体现它的优势。
迪米特法则
1. 迪米特法则也叫最少知识法则。如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用。但是如果一个类需要调用另一个类的某个方法的话,就要通过第三者转发这个调用。
2. 在类的结构设计上,每一个类都要尽量降低成员的访问权限。迪米特法则的根本思想,就是强调了类之间的松耦合。我们在程序设计时,类之间的耦合越弱,越利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。
外观模式
1. 外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层的接口,这个接口使得这一子系统更加容易使用。
3. 外观模式如何使用:首先,在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架构,就需要考虑在数据访问层和业务逻辑层,业务逻辑层和表示层的层与层之间建立外观Façade。其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂。大多数模式在使用时也会产生很多很小很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难。增加外观Façade可以提供一个简单的接口,减少它们之间的依赖。在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,可以为新系统开发一个外观Façade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Façade对象交互,Façade与遗留代码交互所有复杂的操作。
建造者模式
1. 建造者模式:将一个复杂对象的构建与它的表示分离开,使得同样的构建过程可以创建不同的表示。
3. 建造者模式应用场景:它主要用于创建复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临复杂的变化。所以说,建造者模式是在当创建复杂的对象的算法应该独立与该对象的的组成部分以及它们的装配方式时适用的模式。
观察者模式
1. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有的观察者对象,使他们能够更新自己。
3. 观察者模式应用场景:将一个系统分割成一系列相互作用的类有一个很不好的副作用,那就是需要维护相关对象间的一致性。我们不希望维护这个一致性而使各类耦合,这样会给维护,重用,和扩展带来不便。所以当一个对象改变同时会改变其它对象而且它不知道具体有多少对象有待改变,就应该考虑使用观察者模式。当一个抽象模型有两个方面,其中一个方面依赖与另外一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立的改变和复用。总的来讲,观察者模式所做的工作其实是在解除耦合,让耦合的双方都依赖与抽象,而不是依赖与具体,从而使得各自的变化都不会影响到另一边的变化。
4. 委托就是一种引用方法的类型。一旦为委托分配了方法,委托将于该方法具有完全相同的行为。委托方法的使用可以像其它任何方法一样,具有参数和返回值。委托可以看成是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。一个委托可以搭载多个方法,所有的方法被依次的唤起,更重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类。(可以转到客户端来定义观察者,减少了通知者与观察者的耦合)
抽象工厂模式
1. 抽象工厂模式:提供一个创建一系列相关或相互依赖的对象的接口,而无需指定它们具体的类。
3. 它的坏处体现在:如果要增加一个Project表,就要增加三个类,修改三个类才可以实现。这是可以考虑用简单工厂模式,在逻辑部分用分支条件判断语句。
4. 利用反射技术可以动态的实例化一个类。格式为Assembly.Load(“程序集名称”).CreateInstance(“命名空间名称.类名”);
状态模式
1. 状态模式的定义:当一个对象的内部状态改变时允许改变其行为,这个对象看起来像是改变了其类。
2. 状态模式的应用场景:状态模式主要解决的是当控制一个对象状态转换的条件过于复杂的情况。把状态判断的逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当一个对象的行为取决与它的状态,并且它必须在运行时刻根据它的状态来改变它的行为时,就可以考虑使用状态模式了。
4. 状态模式的好处是将于特定状态相关的行为局部化,并且将不同状态的行为分离开。目的是为了消除庞大的if语句,通过把各种状态转移逻辑分布到state的子类之间,来减少相互间的依赖。
适配器模式
1. 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
2. 适配器模式应用场景:系统的数据和行为都正确,但接口不符时,我们应该考虑使用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。 适配器模式主要是应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
4. 当双方都不太容易修改时才要用适配器。DataAdapter用作DataSet和数据源之间的适配器以便检索和保存数据。DataAdapter通过映射Fill(这更改了DataSet中的数据以便与数据源中的数据相匹配)和Update(修改了数据源中心的数据以便与DataSet中的数据想匹配)。
备忘录模式
1. 备忘录模式:在不破坏封装的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态,这样就可将该对象恢复到原先保存的状态。
组合模式
1. 将对象组合成树形结构以表示部分—整体的层次结构,组合模式使得用户对单个对象和对组合对象的使用具有一致性。
3. List<Component>也可以定义树形结构。
4. 组合模式使用场景:当发现需求中是体现部分与整体结构层次时,以及你希望用户可以忽略组合对象与单个对象的不同,统一使用组合结构的所有对象,就应该考虑使用组合模式了。
迭代器模式
1. 迭代器模式:提供一种方法顺序访问一个聚合对象的各个元素,而又不暴露该对象的内部表示。
2. 迭代器模式使用场景:当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,就要用这个模式。
5. 在.NET中用foreach in 就可以了
单例模式
1. 单例模式定义:保证一个类只有一个实例,并提供一个访问它的全局访问点。
2. 通常我们可以让一个全局变量使得一个对象被访问,但他不能防止你实例化多个对象。一个最好的办法就是,让类自身负责维护它的唯一实例,这个类可以保证没有其它的实例可以被创建,并且它可以提供一个访问该实例的方法。
合成/聚合复用原则
1. 尽量使用合成/聚合,尽量不用类的继承。
2. 聚合表示一种弱的拥有关系,体现的是A对象可以包含B对象,而B对象不是A对象的一部分。合成是一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。
3. 优先使用对象的合成/聚合将有助与你保持每个类被封装,并被集中到单个任务上,这样类和类继承层次会保持较小的规模,并且不太可能被继承为不可控制的庞然大物。
4. 将抽象部分与它的实现部分分离,使它们可以独立的变化。其中抽象与实现的分离是指抽象类和派生类用来实现自己的对象彼此独立。我的理解是实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。
命令模式
1. 命令模式:将一个请求封装为一个对象,从而使你可用不同的请求对客户
3. 命令模式的优点:第一,它能够很容易的设计出一个命令队列;第二,在需要的情况下,能够较容易的将命令记入日志;第三,允许接受的一方决定是否否决请求。第四,能够很容易的对请求进行撤销和重做;第五,由于加进新的具体类不影响其它的类,因此增加新的具体类很容易。总之,命令模式把请求一个操作的对象与知道怎么执行一个操作的对象分离开。
职责链模式
1. 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传送该请求,直到有一个对象处理它为止。
3. 职责链的关键是当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandle对象负责处理它。这样使得接收者和发送者都没有对方的明确信息,且链中的对象自己也不知道链的结构,结果是职责链可简化对象间的相互连接,它们仅需要保持一个指向其后继者的引用,而不需要保持它所有的候选接受者的引用
中介者模式
1. 中介者模式:用一个中介者来封装一系列对象的交互。中介者使对象不需要显式的相互引用,从而使其耦合松散,而且可以独立改变它们之间的交互。
3. 中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的场合,以及想定制一个分布在多个类中的行为,而又不想生成太多子类的场合。
享元模式
1. 运用共享技术有效的支持大量细粒度的对象。
3. 享元模式的应用场景:如果一个应用 程序使用了大量的对象,而大量的对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以为外部状态,如果删除对象的外部状态,那就可以用较少的共享对象取代很多子对象,此时可以考虑使用享元模式。
访问者模式
1. 访问者模式表示一个作用于某对象结构中的各元素的操作。它使你可以考虑在不改变各元素类的前提下定义作用于这些元素的新操作。