標籤:

一個靜態類或者非靜態類,多個方法依賴一個函數,如何實現?

每個方法(方法數量很多)的開始都要調用一個許可權判斷函數,每一個方法的結尾都要調用一個日誌記錄方法,如何編寫能夠一次性把所有的依賴關係都聲明?這種設計模式叫做什麼模式?有點像sigslot.,希望大神幫忙。


AOP(面向切面編程)

下面是一個JDK動態代理的例子,代理還有很多其他實現方式。

用Cglib的話就不要求被代理對象有介面(你直接使用SpringAOP算了)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Main {
public static void main(String[] args) {
Demo demo = new DemoImpl();
demo.foo();
demo.bar();

System.out.println("======");
demo = (Demo) Proxy.newProxyInstance(demo.getClass().getClassLoader(),
demo.getClass().getInterfaces(),
new MyInvocationHandler(demo));
demo.foo();
demo.bar();
}

private static class MyInvocationHandler implements InvocationHandler {
private Demo demo;

public MyInvocationHandler(Demo demo) {
this.demo = demo;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("foo")) {
System.out.println("before invoke");
method.invoke(demo, args);
System.out.println("after invoke");
} else {
System.out.println("before invoke");
System.out.println("cant invode: need login");
System.out.println("after invoke");
}
return null;
}
}

public static interface Demo {
void foo();

void bar();
}

public static class DemoImpl implements Demo {
public void foo() {
System.out.println("foo()");
}

public void bar() {
System.out.println("bar()");
}
}

}


AOP or Proxy Pattern


這個不是OO領域的問題,所以在那本書是找不到所謂的模式的,說的我又想吐槽那本書了,哎,算了。

從這個需求來說,一般來說實現方式是InvokeProxy

即方法調用代理,即不直接調用方法,而使用一個代理去調用,.Net Remoting的透明代理,WCF自動構建的客戶端代理乃至MVC的ActionInvoker都是這個思想的實現。

大體上就是這樣。


不嫌麻煩用代理

嫌麻煩用依賴注入框架 Method Injection

不動腦子簡單寫就用wrapper class


有好些辦法可以實現。

用function A(), function B(), function C()...function Z()表示題主所說的很多個方法,假設有這麼26個。

那麼 @winter的函數調用可以,但是如果是靜態調用,你得用額外的26個方法來包裝,比較吃力。如果是動態調用,比如採用函數對象這種辦法,可參考策略模式,可以實現。

class Wrapper {
abstract class Function {
abstract void do();
};
Function function;

void do(){
checkPermission();
function.do();
doLog();
}

}

但實際編程時,肯定不可能這26個方法都是函數對象,所以不科學。

那麼 @趙劼的裝飾者模式也可以。

class Wrapper extends Original{

private Original obj;
public Wrapper(Original obj) {
this.obj = obj;
}

public void do(){
checkPermission();
obj.do();
doLog();
}
}

裝飾者模式比策略模式好,因為把攔截抽象到了對象。也就是26個方法如果只屬於4個類,則只需要寫4個Wrapper就行了。但如果這26個方法都分別屬於26個類,那就蛋疼了。

解決這種問題的最佳實踐,我認為肯定是AOP。

假如題主是在Java語言下編程,這個問題就so easy。首先將這26個方法全部加上@annotation。然後對所有annotation表示的方法使用AOP。以下是用spring aop搞定題主問題的示例

public Object AroundDbExecution(final ProceedingJoinPoint pjp) throws NoSuchMethodException, SecurityException {
checkPermission();
Object obj = pjp.proceed();
doLog();
return obj;
}

看,真的是一下搞定所有麻煩,以後再有點什麼監控,事務什麼的處理,直接在這個方法里添加邏輯就行了。


如果是靜態類的話,只是一系列的靜態方法調用,談不上什麼設計模式。

非靜態類的話,Decorator(裝飾者模式)可以用來解決這種問題。

public interface ISomething
{
void DoSomething();
}

public class ConcreteSomething : ISomething
{
public virtual void DoSomething()
{
}
}

public class CheckPermissionSomething : ISomething
{
private readonly ISomething something;

public CheckPermissionSomething(ISomething something)
{
this.something = something;
}

public override void DoSomething()
{
CheckPermission();
something.DoSomething();
PostAction();
}
}

如果你用的是C#或者Java的話,AOP(Aspect Oriented Programming)是解決這種問題的一種比較好的方法。 網上可以搜到很多AOP框架。 AOP適用於Permission, Log, UnitOfWork,Transaction, Cache之類的橫切關注點(Cross-cutting concerns).


#define DEF_FUN(decl, body)

decl {

checkPermission();

body

exitFun();

}


如果有相應的語言特性,就用語言特性。

如果你用的語言可以將一個函數轉化為對象的話。

Invoker模式也是一個選擇。

Invoke(function) {

Do some things

function()

Do some things

}


我怎麼覺得你要求的這種可以使用 裝飾者模式實現呢


其實用 Promise 比較好辦啦. 現在自己的應用後台 API 就是用的這種形式.

function specificAPI() {
// do some fancy jobs and return a promise.
}

function checkPermission() {
// check permission and return a promise.
}

// common logic.
checkPermission()
.then(specificAPI)
.then(function (result) {
// do something with the result, e.g. write to response stream.
});


推薦閱讀:

C++模版類如何動態獲取類型?
c++中如何正確實現克隆(原型)模式?
實現同一介面的不同類使用組合實現了多態,但是這破壞了DRY嗎?
設計模式在實際開發中用的多嗎?
設計模式之組合模式

TAG:設計模式 |