Java 有没有一种优雅的方法让类中的每个方法都从某个代码块开始?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31121513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there an elegant way to make every method in a class start with a certain block of code?
提问by kristina
I have a class where every method starts the same way:
我有一个类,其中每个方法都以相同的方式开始:
class Foo {
public void bar() {
if (!fooIsEnabled) return;
//...
}
public void baz() {
if (!fooIsEnabled) return;
//...
}
public void bat() {
if (!fooIsEnabled) return;
//...
}
}
Is there a nice way to require (and hopefully not write each time) the fooIsEnabled
part for every public method in the class?
是否有一种很好的方法来要求(并且希望不是每次都编写)fooIsEnabled
类中每个公共方法的部分?
采纳答案by sstan
I don't know about elegant, but here is a working implementation using Java's built-in java.lang.reflect.Proxy
that enforcesthat all method invocations on Foo
begin by checking the enabled
state.
我不知道优雅,但这里有一个使用 Java 内置的工作实现,java.lang.reflect.Proxy
它强制所有方法调用都Foo
通过检查enabled
状态开始。
main
method:
main
方法:
public static void main(String[] args) {
Foo foo = Foo.newFoo();
foo.setEnabled(false);
foo.bar(); // won't print anything.
foo.setEnabled(true);
foo.bar(); // prints "Executing method bar"
}
Foo
interface:
Foo
界面:
public interface Foo {
boolean getEnabled();
void setEnabled(boolean enable);
void bar();
void baz();
void bat();
// Needs Java 8 to have this convenience method here.
static Foo newFoo() {
FooFactory fooFactory = new FooFactory();
return fooFactory.makeFoo();
}
}
FooFactory
class:
FooFactory
班级:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class FooFactory {
public Foo makeFoo() {
return (Foo) Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Foo.class},
new FooInvocationHandler(new FooImpl()));
}
private static class FooImpl implements Foo {
private boolean enabled = false;
@Override
public boolean getEnabled() {
return this.enabled;
}
@Override
public void setEnabled(boolean enable) {
this.enabled = enable;
}
@Override
public void bar() {
System.out.println("Executing method bar");
}
@Override
public void baz() {
System.out.println("Executing method baz");
}
@Override
public void bat() {
System.out.println("Executing method bat");
}
}
private static class FooInvocationHandler implements InvocationHandler {
private FooImpl fooImpl;
public FooInvocationHandler(FooImpl fooImpl) {
this.fooImpl = fooImpl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Foo.class &&
!method.getName().equals("getEnabled") &&
!method.getName().equals("setEnabled")) {
if (!this.fooImpl.getEnabled()) {
return null;
}
}
return method.invoke(this.fooImpl, args);
}
}
}
As others have pointed out, it does seem like overkill for what you need if you only have a handful of methods to worry about.
正如其他人所指出的那样,如果您只需要担心几种方法,那么对于您所需要的东西来说似乎有点过分了。
That said, there certainly are benefits:
也就是说,肯定有好处:
- A certain separation of concerns is achieved, because
Foo
's method implementations don't have to worry about theenabled
check cross-cutting concern. Instead, the method's code only needs to worry about what the method's primary purpose is, nothing more. - There is no way for an innocent developer to add a new method to the
Foo
class and mistakenly "forget" to add theenabled
check. Theenabled
check behavior is automatically inherited by any newly added method. - If you need to add another cross-cutting concern, or if you need to enhance the
enabled
check, it's very easy to do so safely and in one place. - It is kind of nice that you can get this AOP-like behavior with built-in Java functionality. You are not forced into having to integrate some other framework like
Spring
, though they can definitely be good options too.
- 实现了一定的关注点分离,因为
Foo
的方法实现不必担心enabled
检查横切关注点。相反,方法的代码只需要关心方法的主要目的是什么,仅此而已。 - 无辜的开发人员没有办法在
Foo
类中添加新方法并错误地“忘记”添加enabled
检查。该enabled
检查的行为由新添加的方法自动继承。 - 如果您需要添加另一个横切关注点,或者如果您需要增强
enabled
检查,很容易在一个地方安全地这样做。 - 很高兴您可以通过内置的 Java 功能获得这种类似 AOP 的行为。您不必被迫集成一些其他框架,例如
Spring
,尽管它们也绝对是不错的选择。
To be fair, some of the downsides are:
公平地说,一些缺点是:
- Some of the implementation code that handles the proxy invocations is ugly. Some would also say that having inner classes to prevent instantiation of the
FooImpl
class is ugly. - If you want to add a new method to
Foo
, you have to make a change in 2 spots: the implementation class and the interface. Not a big deal, but it's still a bit more work. - Proxy invocations are not free. There is a certain performance overhead. For general use though, it won't be noticeable. See herefor more information.
- 一些处理代理调用的实现代码很丑陋。有些人还会说使用内部类来阻止类的实例化
FooImpl
是丑陋的。 - 如果要向 中添加新方法
Foo
,则必须在两个地方进行更改:实现类和接口。没什么大不了的,但它仍然需要更多的工作。 - 代理调用不是免费的。有一定的性能开销。但是对于一般用途,它不会引起注意。请参阅此处了解更多信息。
EDIT:
编辑:
Fabian Streitel's comment got me thinking about 2 annoyances with my above solution that, I'll admit, I'm not happy about myself:
Fabian Streitel 的评论让我想到了上述解决方案的两个烦恼,我承认,我对自己不满意:
- The invocation handler uses magic strings to skip the "enabled-check" on the "getEnabled" and "setEnabled" methods. This can easily break if the method names are refactored.
- If there was a case where new methods need to be added that should not inherit the "enabled-check" behavior, then it can be pretty easy for the developer to get this wrong, and at the very least, it would mean adding more magic strings.
- 调用处理程序使用魔术字符串跳过“getEnabled”和“setEnabled”方法上的“enabled-check”。如果重构方法名称,这很容易中断。
- 如果存在需要添加不应继承“启用检查”行为的新方法的情况,那么开发人员很容易出错,至少,这意味着添加更多魔法字符串。
To resolve point #1, and to at least ease the problem with point #2, I would create an annotation BypassCheck
(or something similar) that I could use to mark the methods in the Foo
interface for which I don't want to perform the "enabled check". This way, I don't need magic strings at all, and it becomes a lot easier for a developer to correctly add a new method in this special case.
为了解决第 1 点,并至少缓解第 2 点的问题,我将创建一个注释BypassCheck
(或类似的东西),我可以用它来标记Foo
接口中我不想执行“启用检查”。这样,我根本不需要魔法字符串,开发人员在这种特殊情况下正确添加新方法变得容易得多。
Using the annotation solution, the code would look like this:
使用注释解决方案,代码如下所示:
main
method:
main
方法:
public static void main(String[] args) {
Foo foo = Foo.newFoo();
foo.setEnabled(false);
foo.bar(); // won't print anything.
foo.setEnabled(true);
foo.bar(); // prints "Executing method bar"
}
BypassCheck
annotation:
BypassCheck
注解:
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BypassCheck {
}
Foo
interface:
Foo
界面:
public interface Foo {
@BypassCheck boolean getEnabled();
@BypassCheck void setEnabled(boolean enable);
void bar();
void baz();
void bat();
// Needs Java 8 to have this convenience method here.
static Foo newFoo() {
FooFactory fooFactory = new FooFactory();
return fooFactory.makeFoo();
}
}
FooFactory
class:
FooFactory
班级:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class FooFactory {
public Foo makeFoo() {
return (Foo) Proxy.newProxyInstance(
this.getClass().getClassLoader(),
new Class[]{Foo.class},
new FooInvocationHandler(new FooImpl()));
}
private static class FooImpl implements Foo {
private boolean enabled = false;
@Override
public boolean getEnabled() {
return this.enabled;
}
@Override
public void setEnabled(boolean enable) {
this.enabled = enable;
}
@Override
public void bar() {
System.out.println("Executing method bar");
}
@Override
public void baz() {
System.out.println("Executing method baz");
}
@Override
public void bat() {
System.out.println("Executing method bat");
}
}
private static class FooInvocationHandler implements InvocationHandler {
private FooImpl fooImpl;
public FooInvocationHandler(FooImpl fooImpl) {
this.fooImpl = fooImpl;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getDeclaringClass() == Foo.class
&& !method.isAnnotationPresent(BypassCheck.class) // no magic strings
&& !this.fooImpl.getEnabled()) {
return null;
}
return method.invoke(this.fooImpl, args);
}
}
}
回答by David P. Caldwell
Yes, but it's a bit of work, so it depends how important it is to you.
是的,但这需要一些工作,所以这取决于它对您的重要性。
You can define the class as an interface, write a delegate implementation, and then use java.lang.reflect.Proxy
to implement the interface with methods that do the shared portion and then conditionally call the delegate.
您可以将类定义为接口,编写委托实现,然后使用java.lang.reflect.Proxy
执行共享部分的方法来实现接口,然后有条件地调用委托。
interface Foo {
public void bar();
public void baz();
public void bat();
}
class FooImpl implements Foo {
public void bar() {
//... <-- your logic represented by this notation above
}
public void baz() {
//... <-- your logic represented by this notation above
}
// and so forth
}
Foo underlying = new FooImpl();
InvocationHandler handler = new MyInvocationHandler(underlying);
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);
Your MyInvocationHandler
can look something like this (error handling and class scaffolding omitted, assuming fooIsEnabled
is defined somewhere accessible):
你MyInvocationHandler
可以看起来像这样(错误处理和类脚手架被省略,假设fooIsEnabled
在某个可访问的地方定义):
public Object invoke(Object proxy, Method method, Object[] args) {
if (!fooIsEnabled) return null;
return method.invoke(underlying, args);
}
It's not incredibly pretty. But unlike various commenters, I'd do it, as I think repetition is a more important risk than this kind of density, and you'll be able to produce the "feel" of your real class, with this somewhat inscrutable wrapper added on very locally in just a couple of lines of code.
它不是非常漂亮。但与各种评论者不同,我会这样做,因为我认为重复是比这种密度更重要的风险,并且您将能够产生真正班级的“感觉”,加上这个有点难以理解的包装只需几行代码就非常本地化。
See the Java documentationfor details on dynamic proxy classes.
有关动态代理类的详细信息,请参阅Java 文档。
回答by damix911
This question is closely related to aspect-oriented programming. AspectJ is an AOP extension of Java and you may give it a look to get some ispiration.
这个问题与面向方面的编程密切相关。AspectJ 是 Java 的 AOP 扩展,您可以看看它以获得一些灵感。
As far as I know there is no direct support for AOP in Java. There are some GOF patterns that relate to it, like for instance Template Methodand Strategybut it will not really save you lines of code.
据我所知,Java 中没有对 AOP 的直接支持。有一些与之相关的 GOF 模式,例如模板方法和策略,但它不会真正为您节省代码行。
In Java and most other languages you could define the recurrent logic you need in functions and adopt a so-called disciplined coding approach in which you call them at the right time.
在 Java 和大多数其他语言中,您可以在函数中定义所需的循环逻辑,并采用所谓的规范编码方法,在该方法中您可以在正确的时间调用它们。
public void checkBalance() {
checkSomePrecondition();
...
checkSomePostcondition();
}
However this would not fit your case because you would like the factored-out code to be able to return from checkBalance
. In languages that support macros (like C/C++) you could define checkSomePrecondition
and checkSomePostcondition
as macros and they would simply be replaced by the preprocessor before the compiler is even invoked:
但是,这不适合您的情况,因为您希望分解后的代码能够从checkBalance
. 在语言的支持宏(如C / C ++),你可以定义checkSomePrecondition
并checkSomePostcondition
为宏,他们会简单地由预处理器替换的编译器,甚至调用之前:
#define checkSomePrecondition \
if (!fooIsEnabled) return;
Java does not have this out of the box. This may offend someone but I did use automatic code generation and template engines to automate repetitive coding tasks in the past. If you process your Java files before compiling them with a suitable preprocessor, for instance Jinja2, you could do something similar to what is possible in C.
Java 没有开箱即用的功能。这可能会冒犯某些人,但我过去确实使用自动代码生成和模板引擎来自动执行重复的编码任务。如果在使用合适的预处理器(例如 Jinja2)编译 Java 文件之前对其进行处理,则可以执行类似于 C 中可能的操作。
Possible pure Java approach
可能的纯 Java 方法
If you are looking for a pure Java solution, what you may find is probably not going to be concise. But, it could still factor out common parts of your program and avoid code duplication and bugs. You could do something like this (it's some sort of Strategy-inspired pattern). Note that in C# and Java 8, and in other languages in which functions are a little easier to handle, this approach may actually look nice.
如果您正在寻找纯 Java 解决方案,您可能会发现可能不会很简洁。但是,它仍然可以分解出程序的公共部分并避免代码重复和错误。你可以做这样的事情(这是某种受策略启发的模式)。请注意,在 C# 和 Java 8 以及其他函数更容易处理的语言中,这种方法实际上看起来不错。
public interface Code {
void execute();
}
...
public class Foo {
private bool fooIsEnabled;
private void protect(Code c) {
if (!fooIsEnabled) return;
c.execute();
}
public void bar() {
protect(new Code {
public void execute() {
System.out.println("bar");
}
});
}
public void baz() {
protect(new Code {
public void execute() {
System.out.println("baz");
}
});
}
public void bat() {
protect(new Code {
public void execute() {
System.out.println("bat");
}
});
}
}
Kinda of a real-world scenario
有点像现实世界的场景
You are developing a class to send data frames to an industrial robot. The robot takes time to complete a command. Once the command is completed, it sends you a control frame back. The robot may get damaged if it receives a new command while the previous is still being executed. Your program uses a DataLink
class to send and receive frames to and from the robot. You need to protect access to the DataLink
instance.
您正在开发一个向工业机器人发送数据帧的类。机器人需要时间来完成命令。命令完成后,它会向您发送一个控制帧。如果在前一个命令仍在执行时接收到新命令,则机器人可能会损坏。您的程序使用一个DataLink
类来向机器人发送帧和从机器人接收帧。您需要保护对DataLink
实例的访问。
The user interface thread calls RobotController.left
, right
, up
or down
when the user clicks the buttons, but also calls BaseController.tick
at regular intervals, in order to reenable command forwarding to the private DataLink
instance.
用户界面线程调用RobotController.left
,right
,up
或者down
当用户点击按钮,而且还要求BaseController.tick
定期,以重新启用命令转发到私DataLink
实例。
interface Code {
void ready(DataLink dataLink);
}
class BaseController {
private DataLink mDataLink;
private boolean mReady = false;
private Queue<Code> mEnqueued = new LinkedList<Code>();
public BaseController(DataLink dl) {
mDataLink = dl;
}
protected void protect(Code c) {
if (mReady) {
mReady = false;
c.ready(mDataLink);
}
else {
mEnqueue.add(c);
}
}
public void tick() {
byte[] frame = mDataLink.readWithTimeout(/* Not more than 50 ms */);
if (frame != null && /* Check that it's an ACK frame */) {
if (mEnqueued.isEmpty()) {
mReady = true;
}
else {
Code c = mEnqueued.remove();
c.ready(mDataLink);
}
}
}
}
class RobotController extends BaseController {
public void left(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'left' by amount */);
}});
}
public void right(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'right' by amount */);
}});
}
public void up(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'up' by amount */);
}});
}
public void down(float amount) {
protect(new Code() { public void ready(DataLink dataLink) {
dataLink.write(/* Create a byte[] that means 'down' by amount */);
}});
}
}
回答by Gondy
I would consider refactoring. This pattern is heavily breaking DRY pattern (Don't repeat yourself). I believe this break this class responsibility. But this depends on your control of code. Your question is very open - where are you calling Foo
instance?
我会考虑重构。这种模式严重破坏了 DRY 模式(不要重复自己)。我相信这打破了这个班级的责任。但这取决于您对代码的控制。你的问题很开放 - 你在哪里调用Foo
实例?
I suppose you have code like
我想你有这样的代码
foo.bar(); // does nothing if !fooEnabled
foo.baz(); // does also nothing
foo.bat(); // also
maybe you should call it something like this way:
也许你应该这样称呼它:
if (fooEnabled) {
foo.bat();
foo.baz();
...
}
And keep it clean. For example, logging:
并保持清洁。例如,日志记录:
this.logger.debug(createResourceExpensiveDump())
a logger
is not asking himself, if debug is enabled. It just logs.
alogger
不是问自己,是否启用了调试。它只是记录。
Instead, calling class need to check this:
相反,调用类需要检查:
if (this.logger.isDebugEnabled()) {
this.logger.debug(createResourceExpensiveDump())
}
If this is a library and you cannot control calling of this class, throw an IllegalStateException
which explains why, if this calling is illegal and cause trouble.
如果这是一个库并且你不能控制这个类的IllegalStateException
调用,如果这个调用是非法的并引起麻烦,抛出一个解释原因的 。
回答by Victor
There is a lot of good suggestions.. what you can do to strike your problem is think in the State Pattern and implement it.
有很多很好的建议......你可以做些什么来解决你的问题,那就是在状态模式中思考并实施它。
Take a look at this code snippet.. perhaps it will get you to an idea. In this scenario looks like you want to modify the entire methods implementation based on the internal state of the object. Please recall that the sum of the methods in a object is knows as behavior.
看看这个代码片段......也许它会让你有一个想法。在这种情况下,您似乎想要根据对象的内部状态修改整个方法实现。请记住,对象中方法的总和称为行为。
public class Foo {
private FooBehaviour currentBehaviour = new FooEnabledBehaviour (); // or disabled, or use a static factory method for getting the default behaviour
public void bar() {
currentBehaviour.bar();
}
public void baz() {
currentBehaviour.baz();
}
public void bat() {
currentBehaviour.bat();
}
public void setFooEnabled (boolean fooEnabled) { // when you set fooEnabel, you are changing at runtime what implementation will be called.
if (fooEnabled) {
currentBehaviour = new FooEnabledBehaviour ();
} else {
currentBehaviour = new FooDisabledBehaviour ();
}
}
private interface FooBehaviour {
public void bar();
public void baz();
public void bat();
}
// RENEMBER THAT instance method of inner classes can refer directly to instance members defined in its enclosing class
private class FooEnabledBehaviour implements FooBehaviour {
public void bar() {
// do what you want... when is enabled
}
public void baz() {}
public void bat() {}
}
private class FooDisabledBehaviour implements FooBehaviour {
public void bar() {
// do what you want... when is desibled
}
public void baz() {}
public void bat() {}
}
}
Hope you like it!
希望你喜欢!
P.D: Is an implementation of the State Pattern (also knows as Strategy depending on the context.. but the principles are just the same).
PD:是状态模式的一种实现(根据上下文也称为策略......但原则是一样的)。
回答by LJ2
As is pointed out in other answers, the Strategy Design Patternis an appropriate design pattern to follow to simplify this code. I've illustrated it here using method invocation through reflection, but there are any number of mechanisms that you could use to get the same effect.
正如其他答案中所指出的那样,策略设计模式是一种适当的设计模式,可以遵循以简化此代码。我在这里使用通过反射的方法调用进行了说明,但是您可以使用多种机制来获得相同的效果。
class Foo {
public static void main(String[] args) {
Foo foo = new Foo();
foo.fooIsEnabled = false;
foo.execute("bar");
foo.fooIsEnabled = true;
foo.execute("baz");
}
boolean fooIsEnabled;
public void execute(String method) {
if(!fooIsEnabled) {return;}
try {
this.getClass().getDeclaredMethod(method, (Class<?>[])null).invoke(this, (Object[])null);
}
catch(Exception e) {
// best to handle each exception type separately
e.printStackTrace();
}
}
// Changed methods to private to reinforce usage of execute method
private void bar() {
System.out.println("bar called");
// bar stuff here...
}
private void baz() {
System.out.println("baz called");
// baz stuff here...
}
private void bat() {
System.out.println("bat called");
// bat stuff here...
}
}
回答by glglgl
I have another approach: have a
我有另一种方法:有一个
interface Foo {
public void bar();
public void baz();
public void bat();
}
class FooImpl implements Foo {
public void bar() {
//...
}
public void baz() {
//...
}
public void bat() {
//...
}
}
class NullFoo implements Foo {
static NullFoo DEFAULT = new NullFoo();
public void bar() {}
public void baz() {}
public void bat() {}
}
}
}
and then you can do
然后你可以做
(isFooEnabled ? foo : NullFoo.DEFAULT).bar();
Maybe you can even replace the isFooEnabled
with a Foo
variable which either holds the FooImpl
to be used or the NullFoo.DEFAULT
. Then the call is simpler again:
也许您甚至可以isFooEnabled
用一个Foo
变量替换 the ,该变量要么包含FooImpl
要使用的 要么NullFoo.DEFAULT
。然后调用又简单了:
Foo toBeUsed = isFooEnabled ? foo : NullFoo.DEFAULT;
toBeUsed.bar();
toBeUsed.baz();
toBeUsed.bat();
BTW, this is called the "Null pattern".
顺便说一句,这被称为“空模式”。
回答by Konrad H?ffner
It seems like the class does nothing when Foo is not enabled so why not express this at a higher level where you create or get the Foo instance?
当 Foo 未启用时,该类似乎什么都不做,那么为什么不在创建或获取 Foo 实例的更高级别表达这一点呢?
class FooFactory
{
static public Foo getFoo()
{
return isFooEnabled ? new Foo() : null;
}
}
...
Foo foo = FooFactory.getFoo();
if(foo!=null)
{
foo.bar();
....
}
This only works if isFooEnabled is a constant though. In a general case, you could create your own annotation.
这仅在 isFooEnabled 是常量时才有效。在一般情况下,您可以创建自己的注释。
回答by Pepijn Schmitz
IMHO the most elegant and best performing solution to this is to have more than one implementation of Foo, together with a factory method for creating one:
恕我直言,对此最优雅和性能最好的解决方案是拥有多个 Foo 实现,以及用于创建一个的工厂方法:
class Foo {
protected Foo() {
// Prevent direct instantiation
}
public void bar() {
// Do something
}
public static void getFoo() {
return fooEnabled ? new Foo() : new NopFoo();
}
}
class NopFoo extends Foo {
public void bar() {
// Do nothing
}
}
Or a variation:
或变体:
class Foo {
protected Foo() {
// Prevent direct instantiation
}
public void bar() {
// Do something
}
public static void getFoo() {
return fooEnabled ? new Foo() : NOP_FOO;
}
private static Foo NOP_FOO = new Foo() {
public void bar() {
// Do nothing
}
};
}
As sstan points out, even better would be to use an interface:
正如 sstan 指出的那样,使用接口更好:
public interface Foo {
void bar();
static Foo getFoo() {
return fooEnabled ? new FooImpl() : new NopFoo();
}
}
class FooImpl implements Foo {
FooImpl() {
// Prevent direct instantiation
}
public void bar() {
// Do something
}
}
class NopFoo implements Foo {
NopFoo() {
// Prevent direct instantiation
}
public void bar() {
// Do nothing
}
}
Adapt this to the rest of your circumstances (are you creating a new Foo every time or reusing the same instance, etc.)
使其适应您的其他情况(您是每次都创建一个新的 Foo 还是重用相同的实例等)
回答by ehh
There is another solution, using delegate (pointer to function). You can have a unique method that first is doing the validation and then is calling to the relevant method according to the function (parameter) to be called. C# code:
还有另一种解决方案,使用委托(函数指针)。您可以拥有一个独特的方法,首先进行验证,然后根据要调用的函数(参数)调用相关方法。C#代码:
internal delegate void InvokeBaxxxDelegate();
class Test
{
private bool fooIsEnabled;
public Test(bool fooIsEnabled)
{
this.fooIsEnabled = fooIsEnabled;
}
public void Bar()
{
InvokeBaxxx(InvokeBar);
}
public void Baz()
{
InvokeBaxxx(InvokeBaz);
}
public void Bat()
{
InvokeBaxxx(InvokeBat);
}
private void InvokeBaxxx(InvokeBaxxxDelegate invoker)
{
if (!fooIsEnabled) return;
invoker();
}
private void InvokeBar()
{
// do Invoke bar stuff
Console.WriteLine("I am Bar");
}
private void InvokeBaz()
{
// do Invoke bar stuff
Console.WriteLine("I am Baz");
}
private void InvokeBat()
{
// do Invoke bar stuff
Console.WriteLine("I am Bat");
}
}