[design mode] template mode

Posted by Harry57 on Mon, 11 Oct 2021 20:46:46 +0200

Template mode is a behavioral strategy mode. It defines the algorithm framework in the superclass, allowing subclasses to override specific steps without modifying the structure

1. Use

If there is a requirement to generate a file, the file format is

Line 1: file version
Line 2: receiver
Line 3: sender
Line 4: Data

You can define an abstract class first, provide the default steps in the abstract class, and provide the default implementation

public class AbstractFile {

	public void final write() {
		Path path = Paths.get(path());
		version(path);
		receiver(path);
		sender(path);
		data(path);
	}	
	
	abstract String path();	

	protected void version(Path path) {
		Files.write(path, "001".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
	}

	protected void receiver(Path path) {
		Files.write(path, "receiver".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
	}

	protected void sender() {
		Files.write(path, "sender".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
	}

	protected void data() {
	
	}

}

User file, containing user related information

public class UsesrFile extends AbstractFile {
	
	String path() {
		return "C:\Users\56319\Desktop\user.txt";
	}
	
	protected void data() {
		Files.write(path, "user data".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
	}
	
}

Transaction file containing transaction information

public class TradeFile extends AbstractFile {
	
	String path() {
		return "C:\Users\56319\Desktop\trade.txt";
	}
	
	protected void data() {
		Files.write(path, "transaction data ".getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
	}
	
}

In this way, when there is a new type of file to be generated, you can directly override the specific method

2. Common applications

1,Spring

In the Spring framework system, there are many template pattern applications, the most typical of which is the refresh method in AbstractApplicationContext

	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
			prepareRefresh();
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			prepareBeanFactory(beanFactory);

			try {
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				invokeBeanFactoryPostProcessors(beanFactory);

				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();

				initMessageSource();

				initApplicationEventMulticaster();

				onRefresh();

				registerListeners();

				finishBeanFactoryInitialization(beanFactory);

				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				destroyBeans();
				cancelRefresh(ex);
				throw ex;
			}

			finally {
				resetCommonCaches();
				contextRefresh.end();
			}
		}
	}

2,Dubbo

The invoke method in the Invoker interface in Dubbo is the application of template mode. The final internal different strategies are handed over to different classes of doInvoke methods

	public Result invoke(Invocation inv) throws RpcException {
        if (destroyed.get()) {
            throw new RpcException("Rpc invoker for service " + this + " on consumer " + NetUtils.getLocalHost()
                    + " use dubbo version " + Version.getVersion()
                    + " is DESTROYED, can not be invoked any more!");
        }
        RpcInvocation invocation = (RpcInvocation) inv;
        invocation.setInvoker(this);
        if (attachment != null && attachment.size() > 0) {
            invocation.addAttachmentsIfAbsent(attachment);
        }
        Map<String, String> context = RpcContext.getContext().getAttachments();
        if (context != null) {
            invocation.addAttachmentsIfAbsent(context);
        }
        if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)) {
            invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
        }
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);


        try {
            return doInvoke(invocation);
        } catch (InvocationTargetException e) { // biz exception
            Throwable te = e.getTargetException();
            if (te == null) {
                return new RpcResult(e);
            } else {
                if (te instanceof RpcException) {
                    ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                }
                return new RpcResult(te);
            }
        } catch (RpcException e) {
            if (e.isBiz()) {
                return new RpcResult(e);
            } else {
                throw e;
            }
        } catch (Throwable e) {
            return new RpcResult(e);
        }
    }
	//Subclasses implement InjvmInvoker and DubboInvoker
    protected abstract Result doInvoke(Invocation invocation) throws Throwable;

3. Summary

1. Advantages and disadvantages

advantage

  • Reuse code. The default implementation can be written in abstract classes to reduce the amount of code

shortcoming

  • Fixed algorithm steps, difficult to modify, and the more steps, the more difficult it is to maintain
  • When too many subclasses cause subclass explosion, you should consider reconstructing the code, subdivide the subclasses, further abstract the algorithm steps, and establish a new abstract class and class system

2. Application scenario

  • When you clearly know the specific implementation of the business, you can abstract the business steps and implement them in a modular manner

3. Template mode and policy mode

  • The template method is based on Inheritance and can only rewrite some steps in the algorithm
  • The policy pattern is based on composition and can rewrite the whole algorithm

Topics: Java Spring Design Pattern