FP角度下的責任鏈模式(中間件模式,middleware)

責任鏈模式,十分常見,好比說,j2ee裏的filter,express裏的middleware,redux裏的middlewarejava

問題是:怎麼才能夠用最簡單的方式實現一個責任鏈模式?
用數組,鏈表來記錄中間件?這些都想過,後來終於找到一種很簡單的方式,靈感來自於fpexpress

使用者要的是什麼

對於使用者來講,Middleware應該是不可見的,他們想要的只是最後的結果,也就是一個普通的函數:redux

input => output

因此,先定義一個Function接口來表示:數組

public interface Function {
    Object apply(Object input);
}

Middleware是什麼

這個middleware最後抽象出來的樣子,會決定咱們後面的實現方式
Middleware跟Function的區別在於,Middleware除了能拿到input,它還能拿到"下一站"的Function
因此,middleware應該是一個能對Function進行AOP加強的東西:app

(input, Function) => output
public interface Middleware {
	Object apply(Object input, Function f);
}

將Middleware結合到Function

最後,咱們要實現一個結合函數:函數

(oldFunction, Middleware) => newFunction

就是說,給你一個oldFunction和一個Middleware,要返回一個newFunction,就是oldFunction經過Middleware加強之後的東西
這個newFunction,能夠直接交給用戶使用,又或者,能夠繼續給它增長Middlewareunix

public static Function combine(final Function f, final Middleware mid) {
	return new Function() {
		public Object apply(final Object input) {
			return mid.apply(input, f);
		}
	};
}

能夠看到,input是先流進Middleware的,而後裏面幹什麼,就由這個Middleware決定了。code

這樣子,責任鏈就完成了,20行不到的代碼。中間件

public class Chain {
	public interface Function {
		Object apply(Object input);
	}
	public interface Middleware {
		Object apply(Object input, Function f);
	}
	public static Function combine(final Function f, final Middleware mid) {
		return new Function() {
			public Object apply(final Object input) {
				return mid.apply(input, f);
			}
		};
	}
}

與管道模式對比

FP是好東西,去掉了OO裏面那些包裝的概念,思考的時候會更簡單直接。接口

管道模式,也就是unix裏面CLI程序串接起來的模式,對應到fp,其實就是最簡單的函數組合
h(x) | g | f 其實就是 f(g(h(x)))

將責任鏈模式 與 管道模式 對比,會發現,能力上,責任鏈是完勝管道的,由於責任鏈其實是對Function的AOP加強,這種加強,能夠是同時包含了前置的和後置的。
而管道模式的加強,只能是前置的(或者後置的)。

管道模式   :  (Function, Function) => Function     
責任鏈模式 :  (Function, Middleware) => Function
相關文章
相關標籤/搜索