什么是开发模式
开发模式是一套立足于特定背景,且拥有一整套可预测结果的解决方案。可复用设计元素。(这句话很重要,需要反复阅读理解!)
GOF经典开发模式包含以下三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
怎样认识开发模式
认识开发模式,首先我们需要理解"特定背景",其次是"解决方案",最后是欣赏"设计元素"。设计元素包括抽象角度、抽象层次、粒度控制等等许多东西,有很大的艺术性,所以自己体会吧。
理解开发模式
1、工厂方法模式和抽象工厂模式
背景:我们想得到某类东西,这类东西由于属性不相同,因此有许多个性。我们需要根据我们的需求和参数取得具有特定个性的类,怎样解决这个问题呢?
解决方案:我们可以提供一个接口,接受用户参数,然后在接口实现类里根据参数生成对应个性类。当然,还应该抽象出产品的抽象类,建立约束,因为这并不能产出所有的产品。这就是的工厂方法模式。
背景:我们要生产多个产品族,内部结构变动过大也就是所参数量过大,使用传参的方式可能就有点牵强。
解决方案:我们不在通过参数统一判定生产什么产品,而是定义产品的组装结构,通过对组装结构的控制达到灵活处理。关注点放到对产品结构划分和工厂搭配的抽象,这样我们可以通过实例化不同的工厂来达到动产品族输出的控制。(抽象工厂模式)
2、单例模式和享元模式
背景:我们多次使用一个相同的类,如果我们每次使用都创建那系统中不是存在多个相同东西并且占据内存吗,我们需要优化他,减少内存的占用。
解决方案:我们判断该类是否存在,存在我们就拿来用,没有就创建一个用,这样就减少了内存的占用。该方案根据类的不同行为划分为单例模式和享元模式,但两者的解决占用内存的思路是一致的。
3、建造者模式和模板方法模式
背景:在我们的业务时常会遇到事情过于复杂,我们往往会想着分阶段分模块来完成,当我们建立一定的标准流程和模块时,事情的完成变得更加可控。当然,我们某些情况下可能需要重新调整流程,而某些情况下注重模块的完整性。
解决方案:将上面管理方法应用到设计上的就是建造者模式和模板方法模式。建造者模式抽象出流程模块并交给建造者来实现,通过指导者来定制流程解决流程可控性。模板方法模式则是抽象出模块,将模块的个性化实现交到相应子类去实现,保证模块的完整性和个性化设置。
4、原型模式
背景:运行时能否获得某实例的拷贝并创建新对象,因为我不想在进行一次构造了。
解决方案:通过定义原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。原型模式通过操作二进制复制原型,这往往比新建一个速度更快,在需要多次创建对象的情况下能帮助你提高性能。
5、适配器模式
背景:当用户期待接口和现有接口不一致时
解决方案:定义客户期待的接口,然后使用现有接口来实例化客户期待接口。
6、装饰器模式
背景:需要在目标填上一些特殊处理
解决方案:建立一个和被修饰类有相同接口的类,那么如果我们取到被修饰类,我们使用被修饰类来实现相应的方法,同时我们还有加入自己处理的空间。
7、代理模式
背景:不希望直接访问和需要做权限控制,并希望控制访问类的创建减少重复构建消耗
解决方案:建立一个代理类,通过代理来取得对象或执行请求
8、外观模式
背景:背景对外不暴露内部调用,而是简化出服务接口,使不用关心具体的过程。
解决方案:这是服务的接口简化的思想,使用外观类来定制一套服务,并对外提供统一的入口。
9、桥接模式
背景:多维变化中如何让各自部分独立变化
解决方案:将抽象部分与实现部分分离,使它们都可以独立的变化。每个维度建立抽象类,使用抽象类来表示实例的耦合变化
10、组合模式
背景:一个整体由多个部分组成,并需要对部分进行增删改查等操作。
解决方案:将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和使用具有一致性。
11、策略模式
背景:当用户处理问题有多种策略,如何让策略可以独自变化,并使用户可以根据情况选择呢
解决方案:定义一系列的策略,把每一个策略封装起来, 并且使它们可相互替换。用户根据需求配置相应的策略,处理则通过配置的策略进行处理问题。
12、观察者模式
背景:让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
解决方案:抽象出主题和观察者,并向主题注册观察者
13、迭代子模式
背景:顺序地访问一个聚集中的元素而不必暴露聚集的内部表象
解决方案:这和我们List访问方式相同,提供迭代访问而不需要查看存储访问过程。
14、责任链模式
背景:需要根据责任和权力来判断是否处理还是提交给别的处理人处理
解决方案:分离出访问者和处理者,通过处理接口请求处理,处理实例根据据责任和权力来判断是否处理还是提交给别的处理人处理,处理者需要持有下一处理者的信息
15、命令模式
背景:调用者和请求接收者解耦,使得调用者和接收者不直接交互。
解决方案:每一个命令都需要设计一个具体命令类,通过传递命令执行相应内容
16、备忘录模式
背景:需要记录某一之前状态,以便获取或恢复
解决方案:抽象出一个备忘录类来保持之前状态的数据,通过一个管理类来管理这个备忘录类。
17、状态模式
背景:当一个对象的内在状态改变时允许改变其行为
解决方案:将对象的状态独立处理,并在各自状态描述对应的行为,使用各自状态行为去完成请求
18、访问者模式
背景:操作元素相对固定,操作方式多样化
解决方案:每个访问者定义对对应元素的操作方式
19、中介者模式
背景:多个对象需要相互交互,导致了紧密耦合,不利于对象的修改和维护。我们希望只需关心自己能做什么就行,不需要再关系做了之后会对其他对象产生什么影响,也就是无需再维护这些关系。
解决方案:利用第三者来管理关系和交互那就是我的中介,对象只需要知道中介,通过中介进行交互即可。而中介持有所有对象,并负责管理他们的交互关系和逻辑
20、解释器模式
背景:扩展现有语法环境
解决方案:自定义表达式,并使用一套语言规则解析