微服务

传统开发中的景象

程序员们日以继夜,诠释着披星戴月的含义,却不断的沉沦在重复搭 建环境、重复系统部署、重复环境验证、重复代码开发等等的炼狱之中, “感觉身体被掏空”的绝望如影随形。
大型软件项目已成为大量代码的随机而无序的堆积。工程师一旦完成项目,就恐避之不及,不愿再去碰自己几个月来夜以继日的劳动成果。

Restfull

REST — REpresentational State Transfer 表现层状态转移
URL定位资源,用HTTP动词(GET,POST,DELETE,PUT)描述操作。
即通过HTTP动词来实现资源的状态扭转:

  • GET 获取资源
  • POST 新建资源(也可用于更新资源)
  • PUT 更新资源
  • DELETE 删除资源

GET、PUT、DELETE操作是幂等的,安全和幂等的意义在于:当某个操作没有达到预期的目标时,我们可以不停的重试这个操作,而不会对资源产生副作用。
创建操作可以使用POST,也可以使用PUT,区别在于POST是作用在一个集合资源之上的(/uri),而PUT操作是作用在一个具体资源之上的(/uri/xxx),可以理解为,如果URL可以在客户端确定那么就使用PUT,如果是在服务端确定那么就使用POST。

幂等

在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数是指可以使用相同参数重复执行,并能获得相同结果的函数。这些函数不会影响系统状态,也不用担心重复执行会对系统造成改变。例如,“setTrue()”函数就是一个幂等函数,无论多少次执行其结果都是一样的。

CAP理论

任何分布式系统在一致性、可用性、分区容错性三方面不能兼得,最多得其二,因此任何分布式系统的设计只是在三者中的不同取舍。
Consistency(一致性):所有节点上数据时刻同步
Availability(可用性):在一定时间能响应客户端的请求
Partition tolerance(分区容错):允许出现网络分区

分区

分区是指网络分区,分布式系统中各节点不再连通。一个分布式系统里面,节点组成的网络本来应该是连通的。然而可能因为一些故障,使得有些节点之间不连通了,整个网络就分成了几块区域,数据就散布在了这些不连通的区域中。
当一个数据项只在一个节点中保存,那么分区出现后,和这个节点不连通的部分就访问不到这个数据了。这时分区就是无法容忍的。提高分区容忍性的办法就是一个数据项复制到多个节点上。
然而,把数据复制到多个节点会带来一致性的问题。要保证一致,每次写操作就都要等待全部节点写成功,而这等待又会带来可用性的问题。
总的来说就是,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。
实际上这在分布式系统中一般认为P是必须的,所以AC需要权衡。
满足AC意味着网络分区不能发生;而当存在网络分区时,将不再同时保证AC。有一个等价的理论:在一个不可靠的分布式环境中,无法同时满足活性(A)和安全性(C)。

如何解决微服务架构中的身份验证问题?
http://mt.sohu.com/20161221/n476556655.shtml

其它结构型模式

组合模式

组合模式将对象组合成树形结构,以表示部分-整体的层次结构。
它使得用户对单个对象的操作与对组合对象的操作具有一致性。
抽象组件接口中声明添加、删除和一些其它业务方法,节点组件实现所有方法,叶节点只需实现其它业务方法。
组合模式带来的操作一致性是透明方式的体现,叶节点和节点一样也含有添加删除方法,但没有意义。另一种方式是安全方式,即抽象组件接口中不声明添加、删除方法,让树叶和树枝实现不同的接口,但这样客户端调用时需要做判断,带来了操作不一致。
当需求中体现了部分与整体层次的结构时,或者希望用户可以忽略组合对象与单个对象的不同时,就应该考虑使用组合模式了。
很多界面控件的基类中都有Add、Remove方法,这就是典型的组合模式的应用。

享元模式

运用共享技术有效地支持大量细粒度的对象
Flyweight模式的核心是把大量共享的对象收集在一起,使用简单工厂模式进行管理,避免由于大量小对象导致系统内存过渡消耗

代理模式

代理模式和装饰模式有相同点,对装饰器模式来说,装饰者(decorator)和被装饰者(decoratee)都实现同一个接口。对代理模式来说,代理类(proxy class)和真实处理的类(real class)都实现同一个接口。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。
使用的场景不一样。比如IO流使用的装饰者模式,可以层层增加功能。代理模式可以用于增加特殊的功能。有些动态代理不支持多层嵌套。
模式区别除了实现外,最重要的是模式的目的性。代理模式与装饰器模式最根本区别是两者的目的不同,而不在具体的实现差异。

工厂模式

工厂的作用

工厂用来实例化对象,使用工厂是隐藏变化的一种自然结果。
先考虑需要什么对象,然后关注如何创建对象,即先确定对象后定义工厂。

几个与工厂有关的模式

  • 单例模式;
  • 工厂方法模式;
  • 原型模式;
  • 抽象工厂模式;
  • 建造者模式;

它们都归为创建型模式。

管理和使用原则

两种视角:使用视角、创建/管理视角
两个实体之间的关系只能有下面一种,或者为A使用B,或者为A管理B。这样降低耦合度。
分清了对象的定义工作和管理工作后,我们说能事半功倍

工厂模式分为3类:

  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)

简单工厂模式中,产品是抽象的,工厂不是抽象的,在工厂类中面对各种具体产品。这个工厂类不符合开闭原则。工厂类中提供不同方法生成不同的具体产品。调用者面对的是一个工厂类和它们的各个方法。

工厂方法模式定义一个用于创建对象的成员方法,让子类在这个方法中决定创建哪个对象。
工厂方法模式中,产品是抽象的,工厂也是抽象的,每个具体工厂类面对一个具体产品。调用者要面对各个具体工厂类和它们的统一方法。
工厂方法会使得工厂对象的数量增长。可以考虑使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。
工厂方法模式要创建的东西本身是抽象定义的,并且工厂类本身也可能是抽象的。
工厂方法模式将“使用哪些对象”的规则与“如何使用这些对象”的逻辑分离开来。

有时虽然有几组对象,但并不需要每个组都用不同的派生类控制其实例化,可以更加动态一些:使用配置文件指定使用哪些对象,用switch实例化正确的对象。

反射技术
菜鸟程序员碰到问题,只会用时间来摆平。所以即使整天加班,老板也不想给加工资。
所有在用简单工厂的地方,都可以考虑用反射技术+配置文件来去除switch或if,解除分支判断带来的耦合。

Abstract Factory模式为创建一组相关的对象提供一个接口,无需指定具体类。注意这里是创建一组对象,即接口中可能提供每种对象的创建方法。

抽象工厂模式与工厂方法模式的区别
工厂方法模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂方法模式的一种推广。
工厂方法模式用来创建一个产品的等级结构,而抽象工厂模式用来创建多个产品的等级结构。工厂方法创建一般只有一个方法,创建一种产品。抽象工厂一般有多个方法,创建一系列产品。
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。
工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。

switch语句说明:
这里可能需要抽象:
需要多态行为;
存在职责错放;
工厂模式并不能消除switch,它将使用switch的职责从调用者中转移了。
switch语句本身没有问题,只有在switch语句互相耦合,比如许多switch语句使用同一个变量作为开关时,这种连接点变成一种依赖性,带来复杂和bug。

示例:
在java中,iterator()方法是工厂方法。
在c++中,begin(),end()都是工厂方法。

一个工厂方法的细节扩展:模板工厂方法
在模板模式中,抽象类中的一个模板方法是用来创建抽象对象的,创建何种具体类推迟到子类中实现。 这个模板工厂方法一般是保护的。

另一个细节延伸模式:建造者模式
建造者模式是围绕构建过程展开的模式。
用于创建一些复杂的对象,这些对象内部构建间的建造过程顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
建造者继承建造接口类,必须实现所有技能;指挥者指挥建造者按顺序施展一些技能。
建造者模式可以把创建复杂对象的算法从该对象的组成部分中独立出来。

可以觉察到,模板工厂方法和建造者模式也是相似的。

再一个建造者模式:Prototype 原型模式
它就是Clone已有对象,基类中提供Clone(),Copy()方法,Clone()方法实现浅复制,Copy()方法实现深复制。

设计模式的分类

根据概念性动机分3类设计模式:

  1. 创建型模式:管理对象的创建。 常用的有单例模式,简单工厂模式,工厂方法模式,另外还有原型模式,抽象工厂模式,建造者模式
  2. 结构型模式:将已有对象加入到的的设计中时,使用结构型模式作为指导。 常用的有外观模式,适配器模式,桥接模式,装饰模式,另外还有组合模式,享元模式,代理模式。
  3. 行为型模式:定义对象时,使用行为型模式指导。 常用的有观察者模式,策略模式,模板方法模式,另外还有命令模式,状态模式,职责链模式,解释器模式,中介者模式,访问者模式,备忘录模式,迭代器模式。

设计模式的推导

标准化结构程序设计->面向对象范型(或思想)->设计原则->设计模式

中介者模式

中介者模式的核心

  • 它贯彻了迪米特法则,通过把众多对象间的交互独立封装出来,使众多的独立对象之间松耦合。

复习迪米特法则

  • 又称最小知识原则,尽量减小两个类间的直接通信。
  • 如果它们之间需要建立调用关系,尽可能通过第三者转发调用。
  • 迪米特法则强调在类的结构设计上,每一个类都应当尽量降低成员的访问权限。
  • 它的根本思想是强调了类之间的松耦合。类之间的耦合越弱,越利于复用。弱耦合关系的类的修改涉及影响最小。

中介者模式的要点

  • 背景是将系统分割出许多对象可以增加复用性,但若对象间的连接太多则又降低了复用性;
  • 通过中介者对象,将网状的连接结构变成以中介者为中心的星形结构;
  • 中介者模式中的主要工作在交互的封装上,控制了集中化,把交互复杂性变为了中介者的复杂性,所以当系统出现多对多交互复杂的对象群时,要先考虑设计的合理性;

职责链模式

职责链模式的核心内容

  • 降低了请求对象和处理对象之间,及处理对象之间的耦合。

职责链模式的要点

  • 构造了一个链结构,链节点只持有下一个节点的引用,不需要知道链中的所有节点,降低了耦合度;
  • 链节点即职责对象,职责类继承自共同的基类,有共同的抽象行为,由于职责权限不同而实现了不同的派生类;
  • 请求者只需要调用第一个职责对象,余下的事全交给它了;
  • 从而请求事件由第一个职责对象自动沿链逐个传递处理;
  • 请求对象在被处理过程中可能被转移处理,或被附加处理