简化版的执行Actitity Command。

一、类图

1、Command

  • Command
public interface Command<T> {

	T execute(CommandContext commandContext);
}
  • DoSomethingCmd
public class DoSomethingCmd implements Command<Void>{

	public Void execute(CommandContext commandContext) {
		System.out.println("do something...");
		return null;
	}

}

2、CommandInterceptor

  • CommandInterceptor
public interface CommandInterceptor {

	<T> T execute(CommandConfig config, Command<T> command);
	
	CommandInterceptor getNext();
	
	void setNext(CommandInterceptor next);
}
  • AbstractCommandInterceptor
public abstract class AbstractCommandInterceptor implements CommandInterceptor{

	protected CommandInterceptor next;
	
	public CommandInterceptor getNext() {
		return this.next;
	}
	
	public void setNext(CommandInterceptor next) {
		this.next = next;
	}
}
  • LogInterceptor
public class LogInterceptor extends AbstractCommandInterceptor{

	public <T> T execute(CommandConfig config, Command<T> command) {
		try{
			System.out.println("start...");
			return next.execute(config, command);
		}finally{
			System.out.println("finish...");
		}
	}

}
  • CommandContextInterceptor
public class CommandContextInterceptor extends AbstractCommandInterceptor{

	protected CommandContextFactory contextFactory;
	protected EngineConfiguration engineConfiguration;
	
	public CommandContextInterceptor(CommandContextFactory contextFactory, EngineConfiguration engineConfiguration) {
		this.contextFactory = contextFactory;
		this.engineConfiguration = engineConfiguration;
	}
	
	public <T> T execute(CommandConfig config, Command<T> command) {
		CommandContext context = Context.getCommandContext();
		boolean contextReused = false;
		if(!config.isReuse() || context == null){
			context = contextFactory.createCommandContext(command);
		}else{
			contextReused = true;
			context.setResult(true);
		}
		try{
			
			Context.setCommandContext(context);
			Context.setEngineConfiguration(engineConfiguration);
			
			return next.execute(config, command);
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(!contextReused){
				context.close();
			}
			Context.removeCommandContext();
			Context.removeEngineConfiguration();
		}
		return null;
	}

}
  • CommandInvoker
public class CommandInvoker extends AbstractCommandInterceptor{

	@SuppressWarnings("unchecked")
	public <T> T execute(final CommandConfig config, final Command<T> command) {
		final CommandContext commandContext = Context.getCommandContext();
		commandContext.getAgenda().planOperation(new Runnable() {
			public void run() {
				commandContext.setResult(command.execute(commandContext));
			}
		});
		executeOperations(commandContext);
		return (T) commandContext.getResult();
	}

	protected void executeOperations(final CommandContext commandContext){
		ActivitiAgenda agenda = commandContext.getAgenda();
		while(!agenda.isEmpty()){
			Runnable runnable = agenda.getNextOperation();
			executeOperation(runnable);
		}
	}

	public void executeOperation(Runnable runnable) {
		runnable.run();
	}
}

3、Agenda

  • Agenda
public interface Agenda {

	boolean isEmpty();
	
	Runnable getNextOperation();
	
	void planOperation(Runnable operation);
}
  • ActivitiAgenda
public interface ActivitiAgenda extends Agenda{

	void planOperation(Runnable operation, String param);
}
  • DefaultActivitiAgenda
public class DefaultActivitiAgenda implements ActivitiAgenda{

	protected LinkedList<Runnable> operations = new LinkedList<Runnable>();
	
	public boolean isEmpty() {
		return operations.isEmpty();
	}

	public Runnable getNextOperation() {
		return operations.poll();
	}

	public void planOperation(Runnable operation) {
		planOperation(operation, null);
	}

	public void planOperation(Runnable operation, String param) {
		operations.add(operation);
	}

}

4、CommandExecutor

  • CommandExecutor
public interface CommandExecutor {

	<T> T execute(CommandConfig config, Command<T> command);
	
	<T> T execute(Command<T> command);
}
  • CommandExecutorImpl
public class CommandExecutorImpl implements CommandExecutor{

	protected CommandConfig defaultConfig;
	protected CommandInterceptor first;
	
	public CommandExecutorImpl(CommandConfig defaultConfig,
			CommandInterceptor first) {
		super();
		this.defaultConfig = defaultConfig;
		this.first = first;
	}
	
	public CommandInterceptor getFirst() {
		return first;
	}

	public void setFirst(CommandInterceptor first) {
		this.first = first;
	}

	public CommandConfig getDefaultConfig() {
		return defaultConfig;
	}

	public void setDefaultConfig(CommandConfig defaultConfig) {
		this.defaultConfig = defaultConfig;
	}

	public <T> T execute(Command<T> command) {
		return first.execute(defaultConfig, command);
	}

	public <T> T execute(CommandConfig config, Command<T> command) {
		return first.execute(config, command);
	}

}

5、CommandContextCloseListener

public interface CommandContextCloseListener {

	void closing(CommandContext commandContext);
	
	void closed(CommandContext commandContext);
}

6、CommandContext

public class CommandContext {

	protected Command<?> command;
	protected ActivitiAgenda agenda;
	protected Throwable exception;
	
	protected List<CommandContextCloseListener> closeListeners;
	
	protected boolean reused;
	protected Object result;
	
	public CommandContext(Command<?> command, EngineConfiguration engineConfiguration) {
		this.command = command;
		this.agenda = engineConfiguration.createAgenda();
	}
	
	public void addCloseListener(CommandContextCloseListener closeListener){
		if(closeListeners == null){
			closeListeners = new ArrayList<CommandContextCloseListener>();
		}
		closeListeners.add(closeListener);
	}
	
	public void close(){
		try{
			executeCloseListenersClosing();
			
			if(exception != null){
				//TODO
				System.out.println("flushSessions...");
			}
			
		}catch(Exception e){
			exception(e);
		}finally{
			//TODO
			executeCloseListenersClosed();
		}
		
	}
	
	protected void executeCloseListenersClosing() {
		if(closeListeners != null){
			try{
				for(CommandContextCloseListener listener : closeListeners){
					listener.closing(this);
				}
			}catch(Throwable exception){
				exception(exception);
			}
		}
	}
	
	protected void executeCloseListenersClosed() {
		if(closeListeners != null){
			try{
				for(CommandContextCloseListener listener : closeListeners){
					listener.closed(this);
				}
			}catch(Throwable exception){
				exception(exception);
			}
		}
	}

	public void exception(Throwable exception){
		if(this.exception == null){
			this.exception = exception;
		}else{
			exception.printStackTrace();
		}
	}
	
	public Command<?> getCommand() {
		return command;
	}
	
	public ActivitiAgenda getAgenda() {
		return agenda;
	}

	public Object getResult() {
		return result;
	}

	public void setResult(Object result) {
		this.result = result;
	}

	public boolean isReused() {
		return reused;
	}

	public void setReused(boolean reused) {
		this.reused = reused;
	}
}

7、CommandConfig

public class CommandConfig {

	private boolean reuse;
	
	public CommandConfig() {
		this.reuse = true;
	}

	public boolean isReuse() {
		return reuse;
	}

	public void setReuse(boolean reuse) {
		this.reuse = reuse;
	}
	
}

8、Context

public class Context {

	protected static ThreadLocal<Stack<CommandContext>> commandContextLocal = new ThreadLocal<Stack<CommandContext>>();
	protected static ThreadLocal<Stack<EngineConfiguration>> engineConfigurationLocal = new ThreadLocal<Stack<EngineConfiguration>>();
	
	public static CommandContext getCommandContext(){
		Stack<CommandContext> stack = getStack(commandContextLocal);
		if(stack.isEmpty()){
			return null;
		}
		return stack.peek();
	}
	
	public static EngineConfiguration getProcessEngineConfiguration(){
		Stack<EngineConfiguration> stack = getStack(engineConfigurationLocal);
		if(stack.isEmpty()){
			return null;
		}
		return stack.peek();
	}
	
	public static void setCommandContext(CommandContext commandContext){
		getStack(commandContextLocal).push(commandContext);
	}
	
	public static void removeCommandContext(){
		getStack(commandContextLocal).pop();
	}
	
	public static void setEngineConfiguration(EngineConfiguration engineConfiguration){
		getStack(engineConfigurationLocal).push(engineConfiguration);
	}
	
	public static void removeEngineConfiguration(){
		getStack(engineConfigurationLocal).pop();
	}
	
	protected static <T> Stack<T> getStack(ThreadLocal<Stack<T>> threadLocal){
		Stack<T> stack = threadLocal.get();
		if(stack == null){
			stack = new Stack<T>();
			threadLocal.set(stack);
		}
		return stack;
	}
}

9、CommandContextFactory

public class CommandContextFactory {

	protected EngineConfiguration engineConfiguration;
	
	public CommandContext createCommandContext(Command<?> command){
		return new CommandContext(command, engineConfiguration);
	}

	public EngineConfiguration getEngineConfiguration() {
		return engineConfiguration;
	}

	public void setEngineConfiguration(EngineConfiguration engineConfiguration) {
		this.engineConfiguration = engineConfiguration;
	}
}

10、EngineConfiguration

public class EngineConfiguration {

	protected CommandConfig defaultCommandConfig;
	protected CommandExecutor commandExecutor;
	protected List<CommandInterceptor> commandInterceptors;
	protected CommandInterceptor commandInvoker;
	
	protected CommandContextFactory commandContextFactory;
	
	public EngineConfiguration() {
		init();
	}
	
	public void init(){
		initCommandContextFactory();

		initCommandConfig();
		initCommandInvoker();
		initCommandInterceptors();
		initCommandExecutor();
	}
	
	private void initCommandInvoker() {
		if(commandInvoker == null){
			commandInvoker = new CommandInvoker();
		}
	}

	private void initCommandConfig() {
		if(defaultCommandConfig == null){
			defaultCommandConfig = new CommandConfig();
		}
	}
	
	private void initCommandInterceptors() {
		if(commandInterceptors == null){
			commandInterceptors = new ArrayList<CommandInterceptor>();
			commandInterceptors.addAll(getDefaultCommandInterceptors());
			commandInterceptors.add(commandInvoker);
		}
	}

	private void initCommandExecutor() {
		if(commandExecutor == null){
			CommandInterceptor first = initInterceptorChain(commandInterceptors);
			commandExecutor = new CommandExecutorImpl(getDefaultCommandConfig(), first);
		}
	}
	
	private void initCommandContextFactory() {
		if(commandContextFactory == null){
			commandContextFactory = new CommandContextFactory();
		}
		commandContextFactory.setEngineConfiguration(this);
	}
	
	private CommandInterceptor initInterceptorChain(List<CommandInterceptor> chain) {
		if(chain == null || chain.isEmpty()){
			throw new RuntimeException("invalid command interceptor chain: " + chain);
		}
		for(int i = 0; i < chain.size() - 1; i++){
			chain.get(i).setNext(chain.get(i + 1));
		}
		return chain.get(0);
	}

	public List<CommandInterceptor> getDefaultCommandInterceptors(){
		List<CommandInterceptor> interceptors = new ArrayList<CommandInterceptor>();
		interceptors.add(new LogInterceptor());
		
		interceptors.add(new CommandContextInterceptor(commandContextFactory, this));
		
		return interceptors;
	}
	
	public ActivitiAgenda createAgenda(){
		return new DefaultActivitiAgenda();
	}
	
	public CommandConfig getDefaultCommandConfig() {
		return defaultCommandConfig;
	}

	public void setDefaultCommandConfig(CommandConfig defaultCommandConfig) {
		this.defaultCommandConfig = defaultCommandConfig;
	}

	public CommandExecutor getCommandExecutor() {
		return commandExecutor;
	}

	public void setCommandExecutor(CommandExecutor commandExecutor) {
		this.commandExecutor = commandExecutor;
	}
}

二、执行Cmd

public class App 
{
    public static void main( String[] args )
    {      
        EngineConfiguration engineConfiguration = new EngineConfiguration();
        engineConfiguration.getCommandExecutor().execute(new DoSomethingCmd());
    }
}

输出:

start...
do something...
finish...