架构师训练营 - 第三周学习总结
本周主要学习设计模式(23种)。设计模式是一种可重复使用的解决方案,每一种模式都描述了一种问题的通用解决方案。
设计模式从功能上主要分为三大类
创建型模式:对类的实例化过程的抽象
结构型模式:将类或者对象结合在一起形成更大的结构
行为型模式:对在不同的对象之间划分责任和算法的抽象化
设计模式从方式上主要分为两大类
类模式:以继承的方式实现模式,静态的
对象模式:以组合的方式实现模式,动态的(推荐)
单例模式
单例模式保证产生单一实例,就是说一个类只产生一个实例。
使用单例模式有两个原因:
是因为只有一个实例,可以减少实例频繁创建和销毁带来的资源消耗
是当多个用户使用这个实例的时候,便于进行统一控制(比如打印机对象)
单例模式有两种实现方式:
饿汉式(推荐)
懒汉式
注意:
一定要有私有构造方法,保证实例只能通过getInstance方法获得
尽量使用饿汉式的实现方式
单例中的成员变量hi多线程重用的,可能会产生意想不到的结果,因此尽量将单例设计为无状态对象(只提供服务,不保存状态)
模板模式
模板方法模式在一个方法中定义一个算法骨架(业务逻辑),并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。
示例代码
说明:templateMethod() 方法定义为 final,是为了避免子类重写它。method1() 和 method2() 定义为 abstract,是为了强迫子类去实现。模板模式把一个算法中不变的流程抽象到父类的模板方法 templateMethod() 中,将可变的部分 method1()、method2() 留给子类 ContreteClass1 和 ContreteClass2 来实现。
具体框架应用有Servlet和Junit。
Servlet的体现:
从上面的代码中我们可以看出,HttpServlet 的 service() 方法就是一个模板方法,它实现了整个 HTTP 请求的执行流程,doGet()、doPost() 是模板中可以由子类来定制的部分。
JUnit TestCase的体现:
在使用 JUnit 测试框架来编写单元测试的时候,我们编写的测试类都要继承框架提供的 TestCase 类。在 TestCase 类中,runBare() 函数是模板方法,它定义了执行测试用例的整体流程:先执行 setUp() 做些准备工作,然后执行 runTest() 运行真正的测试代码,最后执行 tearDown() 做扫尾工作。
策略模式
定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端(这里的客户端代指使用算法的代码)。
策略模式包含一个策略接口和一组实现这个接口的策略类。因为所有的策略类都实现相同的接口,所以,客户端代码基于接口而非实现编程,可以灵活地替换不同的策略。
实例代码:
策略模式会包含一组策略,在使用它们的时候,一般会通过类型(type)来判断创建哪个策略来使用。为了封装创建逻辑,我们需要对客户端代码屏蔽创建细节。我们可以把根据 type 创建策略的逻辑抽离出来,放到工厂类中。
示例代码1,如下:
说明:适合在策略类是无状态的情况,不包含成员变量,只是纯粹的算法实现,事先创建好每个策略对象,缓存到工厂类中,用的时候直接返回。
示例代码2,如下:
说明:适合策略类是有状态的情况,根据业务场景的需要,我们希望每次从工厂方法中,获得的都是新创建的策略对象,而不是缓存好可共享的策略对象。
利用策略模式避免if-else分支判断
假如有示例代码:
策略模式改造后
如果业务场景需要每次都创建不同的策略对象,我们就要用另外一种工厂类的实现方式。
此时工厂类仍然有if-else分支判断,可以配置文件中对应策略接口和策略实现类,通过反射机制调用去除分支判断。
组合模式
将一组对象组织(Compose)成树形结构,以表示一种“部分 - 整体”的层次结构。组合让客户端(在很多设计模式书籍中,“客户端”代指代码的使用者。)可以统一单个对象和组合对象的处理逻辑。
示例代码见第三周作业第二题。
暂时这么多,后面陆陆续续更新,学一个写一个。
评论