zoukankan      html  css  js  c++  java
  • Jfinal源码分析-Render系列方法设计模式

    在学习Jfinal的Render系列方法的设计模式之前,有必要熟悉传统的简单工厂模式、工厂模式以及抽象工厂模式
    Jfinal的Render系列方法中综合了三种工厂的优点,保证了充分的可扩展性。


    当然上图还省略了其他系列的Render类,如:JsonRender、TextRender、ErrorRender、FileRender、RedirectRender、Redirect301Render、NullRender、JavascriptRender、HtmlRender、XmlRender、QrCodeRender

    配置型+抽象工厂:Constants的抽象工厂

    Constants中的常量设置代码:

    /**
     * The constant for JFinal runtime.
     */
    final public class Constants {
    	
    	private boolean devMode = Const.DEFAULT_DEV_MODE;
    	
    	private String baseUploadPath = Const.DEFAULT_BASE_UPLOAD_PATH;
    	private String baseDownloadPath = Const.DEFAULT_BASE_DOWNLOAD_PATH;
    	
    	private String encoding = Const.DEFAULT_ENCODING;
    	private String urlParaSeparator = Const.DEFAULT_URL_PARA_SEPARATOR;
    	private ViewType viewType = Const.DEFAULT_VIEW_TYPE;
    	private String viewExtension = Const.DEFAULT_VIEW_EXTENSION;
    	private int maxPostSize = Const.DEFAULT_MAX_POST_SIZE;
    	private int freeMarkerTemplateUpdateDelay = Const.DEFAULT_FREEMARKER_TEMPLATE_UPDATE_DELAY;	// just for not devMode
    	
    	private ControllerFactory controllerFactory = Const.DEFAULT_CONTROLLER_FACTORY;
    	private int configPluginOrder = Const.DEFAULT_CONFIG_PLUGIN_ORDER;
    	
    	private boolean injectDependency = Const.DEFAULT_INJECT_DEPENDENCY;
    	
    	private ITokenCache tokenCache = null;
    	
    	/**
    	 * Set development mode.
    	 * @param devMode the development mode
    	 */
    	public void setDevMode(boolean devMode) {
    		this.devMode = devMode;
    	}
    	
    	public boolean getDevMode() {
    		return devMode;
    	}
    	
    	/**
    	 * 配置 configPlugin(Plugins me) 在 JFinalConfig 中被调用的次序.
    	 * 
    	 * 取值 1、2、3、4、5 分别表示在 configConstant(..)、configRoute(..)、
    	 * configEngine(..)、configInterceptor(..)、configHandler(...)
    	 * 之后被调用
    	 * 
    	 * 默认值为 2,那么 configPlugin(..) 将在 configRoute(...) 调用之后被调用
    	 * @param 取值只能是 1、2、3、4、5
    	 */
    	public void setConfigPluginOrder(int configPluginOrder) {
    		if (configPluginOrder < 1 || configPluginOrder > 5) {
    			throw new IllegalArgumentException("configPluginOrder 只能取值为:1、2、3、4、5");
    		}
    		this.configPluginOrder = configPluginOrder;
    	}
    	
    	public int getConfigPluginOrder() {
    		return configPluginOrder;
    	}
    	
    	/**
    	 * Set the renderFactory
    	 */
    	public void setRenderFactory(IRenderFactory renderFactory) {
    		if (renderFactory == null) {
    			throw new IllegalArgumentException("renderFactory can not be null.");
    		}
    		RenderManager.me().setRenderFactory(renderFactory);
    	}
    	
    	/**
    	 * 设置 Json 转换工厂实现类,目前支持:JFinalJsonFactory(默认)、JacksonFactory、FastJsonFactory
    	 * 分别支持 JFinalJson、Jackson、FastJson
    	 */
    	public void setJsonFactory(IJsonFactory jsonFactory) {
    		if (jsonFactory == null) {
    			throw new IllegalArgumentException("jsonFactory can not be null.");
    		}
    		JsonManager.me().setDefaultJsonFactory(jsonFactory);
    	}
    	
    	/**
    	 * 设置json转换时日期格式,常用格式有:"yyyy-MM-dd HH:mm:ss"、 "yyyy-MM-dd"
    	 */
    	public void setJsonDatePattern(String datePattern) {
    		if (StrKit.isBlank(datePattern)) {
    			throw new IllegalArgumentException("datePattern can not be blank.");
    		}
    		JsonManager.me().setDefaultDatePattern(datePattern);
    	}
    	
    	public void setCaptchaCache(ICaptchaCache captchaCache) {
    		CaptchaManager.me().setCaptchaCache(captchaCache);
    	}
    	
    	public void setLogFactory(ILogFactory logFactory) {
    		if (logFactory == null) {
    			throw new IllegalArgumentException("logFactory can not be null.");
    		}
    		LogManager.me().setDefaultLogFactory(logFactory);
    	}
    	
    	/**
    	 * Set encoding. The default encoding is UTF-8.
    	 * @param encoding the encoding
    	 */
    	public void setEncoding(String encoding) {
    		if (StrKit.isBlank(encoding)) {
    			throw new IllegalArgumentException("encoding can not be blank.");
    		}
    		this.encoding = encoding;
    	}
    	
    	public String getEncoding() {
    		return encoding;
    	}
    	
    	/**
    	 * 设置自定义的 ControllerFactory 用于创建 Controller 对象
    	 */
    	public void setControllerFactory(ControllerFactory controllerFactory) {
    		if (controllerFactory == null) {
    			throw new IllegalArgumentException("controllerFactory can not be null.");
    		}
    		this.controllerFactory = controllerFactory;
    	}
    	
    	public ControllerFactory getControllerFactory() {
    		return controllerFactory;
    	}
    	
    	/**
    	 * 设置对 Controller、Interceptor 进行依赖注入,默认值为 false
    	 * 
    	 * 被注入对象默认为 singleton,可以通过 Aop.setSingleton(boolean) 配置
    	 * 该默认值。
    	 * 
    	 * 也可通过在被注入的目标类上使用 Singleton 注解覆盖上述默认值,注解配置
    	 * 优先级高于默认配置
    	 */
    	public void setInjectDependency(boolean injectDependency) {
    		this.injectDependency = injectDependency;
    		InterceptorManager.me().setInjectDependency(injectDependency);
    	}
    	
    	public boolean getInjectDependency() {
    		return injectDependency;
    	}
    	
    	/**
    	 * Set ITokenCache implementation otherwise JFinal will use the HttpSesion to hold the token.
    	 * @param tokenCache the token cache
    	 */
    	public void setTokenCache(ITokenCache tokenCache) {
    		this.tokenCache = tokenCache;
    	}
    	
    	public ITokenCache getTokenCache() {
    		return tokenCache;
    	}
    	
    	public String getUrlParaSeparator() {
    		return urlParaSeparator;
    	}
    	
    	public ViewType getViewType() {
    		return viewType;
    	}
    	
    	/**
    	 * Set view type. The default value is ViewType.JFINAL_TEMPLATE
    	 * Controller.render(String view) will use the view type to render the view.
    	 * @param viewType the view type 
    	 */
    	public void setViewType(ViewType viewType) {
    		if (viewType == null) {
    			throw new IllegalArgumentException("viewType can not be null");
    		}
    		this.viewType = viewType;
    	}
    	
    	/**
    	 * Set urlPara separator. The default value is "-"
    	 * @param urlParaSeparator the urlPara separator
    	 */
    	public void setUrlParaSeparator(String urlParaSeparator) {
    		if (StrKit.isBlank(urlParaSeparator) || urlParaSeparator.contains("/")) {
    			throw new IllegalArgumentException("urlParaSepartor can not be blank and can not contains "/"");
    		}
    		this.urlParaSeparator = urlParaSeparator;
    	}
    	
    	public String getViewExtension() {
    		return viewExtension;
    	}
    	
    	/**
    	 * Set view extension for the IRenderFactory.getDefaultRender(...)
    	 * The default value is ".html"
    	 * 
    	 * Example: ".html" or ".ftl"
    	 * @param viewExtension the extension of the view, it must start with dot char "."
    	 */
    	public void setViewExtension(String viewExtension) {
    		this.viewExtension = viewExtension.startsWith(".") ? viewExtension : "." + viewExtension;
    	}
    	
    	/**
    	 * Set error 404 view.
    	 * @param error404View the error 404 view
    	 */
    	public void setError404View(String error404View) {
    		errorViewMapping.put(404, error404View);
    	}
    	
    	/**
    	 * Set error 500 view.
    	 * @param error500View the error 500 view
    	 */
    	public void setError500View(String error500View) {
    		errorViewMapping.put(500, error500View);
    	}
    	
    	/**
    	 * Set error 401 view.
    	 * @param error401View the error 401 view
    	 */
    	public void setError401View(String error401View) {
    		errorViewMapping.put(401, error401View);
    	}
    	
    	/**
    	 * Set error 403 view.
    	 * @param error403View the error 403 view
    	 */
    	public void setError403View(String error403View) {
    		errorViewMapping.put(403, error403View);
    	}
    	
    	private Map<Integer, String> errorViewMapping = new HashMap<Integer, String>();
    	
    	public void setErrorView(int errorCode, String errorView) {
    		errorViewMapping.put(errorCode, errorView);
    	}
    	
    	public String getErrorView(int errorCode) {
    		return errorViewMapping.get(errorCode);
    	}
    	
    	public String getBaseDownloadPath() {
    		return baseDownloadPath;
    	}
    	
    	/**
    	 * Set file base download path for Controller.renderFile(...)
    	 * 设置文件下载基础路径,当路径以 "/" 打头或是以 windows 磁盘盘符打头,
    	 * 则将路径设置为绝对路径,否则路径将是以应用根路径为基础的相对路径
    	 * <pre>
    	 * 例如:
    	 * 1:参数 "/var/www/download" 为绝对路径,下载文件存放在此路径之下
    	 * 2:参数 "download" 为相对路径,下载文件存放在 PathKit.getWebRoot() + "/download" 路径之下
    	 * </pre>
    	 */
    	public void setBaseDownloadPath(String baseDownloadPath) {
    		if (StrKit.isBlank(baseDownloadPath)) {
    			throw new IllegalArgumentException("baseDownloadPath can not be blank.");
    		}
    		this.baseDownloadPath = baseDownloadPath;
    	}
    	
    	/**
    	 * Set file base upload path.
    	 * 设置文件上传保存基础路径,当路径以 "/" 打头或是以 windows 磁盘盘符打头,
    	 * 则将路径设置为绝对路径,否则路径将是以应用根路径为基础的相对路径
    	 * <pre>
    	 * 例如:
    	 * 1:参数 "/var/www/upload" 为绝对路径,上传文件将保存到此路径之下
    	 * 2:参数 "upload" 为相对路径,上传文件将保存到 PathKit.getWebRoot() + "/upload" 路径之下
    	 * </pre>
    	 */
    	public void setBaseUploadPath(String baseUploadPath) {
    		if (StrKit.isBlank(baseUploadPath)) {
    			throw new IllegalArgumentException("baseUploadPath can not be blank.");
    		}
    		this.baseUploadPath = baseUploadPath;
    	}
    	
    	public String getBaseUploadPath() {
    		return baseUploadPath;
    	}
    	
    	public int getMaxPostSize() {
    		return maxPostSize;
    	}
    	
    	/**
    	 * Set max size of http post. The upload file size depend on this value.
    	 */
    	public void setMaxPostSize(int maxPostSize) {
    		this.maxPostSize = maxPostSize;
    	}
    	
    	/**
    	 * Set default base name to load Resource bundle.
    	 * The default value is "i18n".<tr>
    	 * Example:
    	 * setI18nDefaultBaseName("i18n");
    	 */
    	public void setI18nDefaultBaseName(String defaultBaseName) {
    		I18n.setDefaultBaseName(defaultBaseName);
    	}
    	
    	/**
    	 * Set default locale to load Resource bundle.
    	 * The locale string like this: "zh_CN" "en_US".<br>
    	 * Example:
    	 * setI18nDefaultLocale("zh_CN");
    	 */
    	public void setI18nDefaultLocale(String defaultLocale) {
    		I18n.setDefaultLocale(defaultLocale);
    	}
    	
    	/**
    	 * 设置 devMode 之下的 action report 是否在 invocation 之后,默认值为 true
    	 */
    	public void setReportAfterInvocation(boolean reportAfterInvocation) {
    		ActionReporter.setReportAfterInvocation(reportAfterInvocation);
    	}
    	
    	/**
    	 * FreeMarker template update delay for not devMode.
    	 */
    	public void setFreeMarkerTemplateUpdateDelay(int delayInSeconds) {
    		if (delayInSeconds < 0) {
    			throw new IllegalArgumentException("template_update_delay must more than -1.");
    		}
    		this.freeMarkerTemplateUpdateDelay = delayInSeconds;
    	}
    	
    	public int getFreeMarkerTemplateUpdateDelay() {
    		return freeMarkerTemplateUpdateDelay;
    	}
    }
    

    RenderFactory是个简单工厂

    	public void init(Engine engine, Constants constants, ServletContext servletContext) {
    		this.engine = engine;
    		this.constants = constants;
    		this.servletContext = servletContext;
    		
    		// create mainRenderFactory
    		switch (constants.getViewType()) {
    		case JFINAL_TEMPLATE:
    			mainRenderFactory = new MainRenderFactory();
    			break ;
    		case FREE_MARKER:
    			mainRenderFactory = new FreeMarkerRenderFactory();
    			break ;
    		case JSP:
    			mainRenderFactory = new JspRenderFactory();
    			break ;
    		case VELOCITY:
    			mainRenderFactory = new VelocityRenderFactory();
    			break ;
    		}
    	}
    

    抽象的工厂:

    public abstract class Render {
    	
    	protected String view;
    	protected HttpServletRequest request;
    	protected HttpServletResponse response;
    	
    	private static String encoding = Const.DEFAULT_ENCODING;
    	private static boolean devMode = Const.DEFAULT_DEV_MODE;
    	
    	static void init(String encoding, boolean devMode) {
    		Render.encoding = encoding;
    		Render.devMode = devMode;
    	}
    	
    	public static String getEncoding() {
    		return encoding;
    	}
    	
    	public static boolean getDevMode() {
    		return devMode;
    	}
    	
    	public Render setContext(HttpServletRequest request, HttpServletResponse response) {
    		this.request = request;
    		this.response = response;
    		return this;
    	}
    	
    	public Render setContext(HttpServletRequest request, HttpServletResponse response, String viewPath) {
    		this.request = request;
    		this.response = response;
    		if (view != null && view.length() > 0 && view.charAt(0) != '/') {
    			view = viewPath + view;
    		}
    		return this;
    	}
    	
    	public String getView() {
    		return view;
    	}
    	
    	public void setView(String view) {
    		this.view = view;
    	}
    	
    	/**
    	 * Render to client
    	 */
    	public abstract void render();
    }
    

    具体系列产品的实现(以TemplateRender为例):

    /**
     * TemplateRender
     */
    public class TemplateRender extends Render {
    	
    	protected static Engine engine;
    	
    	private static final String contentType = "text/html; charset=" + getEncoding();
    	
    	static void init(Engine engine) {
    		if (engine == null) {
    			throw new IllegalArgumentException("engine can not be null");
    		}
    		TemplateRender.engine = engine;
    	}
    	
    	public TemplateRender(String view) {
    		this.view = view;
    	}
    	
    	public String getContentType() {
    		return contentType;
    	}
    	
    	public void render() {
    		response.setContentType(getContentType());
            
    		Map<Object, Object> data = new HashMap<Object, Object>();
    		for (Enumeration<String> attrs=request.getAttributeNames(); attrs.hasMoreElements();) {
    			String attrName = attrs.nextElement();
    			data.put(attrName, request.getAttribute(attrName));
    		}
    		
    		try {
    			OutputStream os = response.getOutputStream();
    			engine.getTemplate(view).render(data, os);
    		} catch (RuntimeException e) {	// 捕获 ByteWriter.close() 抛出的 RuntimeException
    			Throwable cause = e.getCause();
    			if (cause instanceof IOException) {	// ClientAbortException、EofException 直接或间接继承自 IOException
    				String name = cause.getClass().getSimpleName();
    				if ("ClientAbortException".equals(name) || "EofException".equals(name)) {
    					return ;
    				}
    			}
    			
    			throw e;
    		} catch (IOException e) {
    			throw new RenderException(e);
    		}
    	}
    	
    	public String toString() {
    		return view;
    	}
    }
    

    Render的调用

    	// ----------------
    	// render below ---
    	
    	public Render getRender() {
    		return render;
    	}
    	
    	/**
    	 * Render with any Render which extends Render
    	 */
    	public void render(Render render) {
    		this.render = render;
    	}
    	
    	/**
    	 * Render with view use default type Render configured in JFinalConfig
    	 */
    	public void render(String view) {
    		render = renderManager.getRenderFactory().getRender(view);
    	}
    	
    	/**
    	 * Render template to String content, it is useful for:
    	 * 1: Generate HTML fragment for AJAX request
    	 * 2: Generate email, short message and so on
    	 */
    	public String renderToString(String template, Map data) {
    		if (template.charAt(0) != '/') {
    			template = action.getViewPath() + template;
    		}
    		return renderManager.getEngine().getTemplate(template).renderToString(data);
    	}
    	
    	/**
    	 * Render with JFinal template
    	 */
    	public void renderTemplate(String template) {
    		render = renderManager.getRenderFactory().getTemplateRender(template);
    	}
    	
    	/**
    	 * Render with jsp view
    	 */
    	public void renderJsp(String view) {
    		render = renderManager.getRenderFactory().getJspRender(view);
    	}
    	
    	/**
    	 * Render with freemarker view
    	 */
    	public void renderFreeMarker(String view) {
    		render = renderManager.getRenderFactory().getFreeMarkerRender(view);
    	}
    	
    	/**
    	 * Render with velocity view
    	 */
    	public void renderVelocity(String view) {
    		render = renderManager.getRenderFactory().getVelocityRender(view);
    	}
    	
    	/**
    	 * Render with json
    	 * <p>
    	 * Example:<br>
    	 * renderJson("message", "Save successful");<br>
    	 * renderJson("users", users);<br>
    	 */
    	public void renderJson(String key, Object value) {
    		render = renderManager.getRenderFactory().getJsonRender(key, value);
    	}
    	
    	/**
    	 * Render with json
    	 */
    	public void renderJson() {
    		render = renderManager.getRenderFactory().getJsonRender();
    	}
    	
    	/**
    	 * Render with attributes set by setAttr(...) before.
    	 * <p>
    	 * Example: renderJson(new String[]{"blogList", "user"});
    	 */
    	public void renderJson(String[] attrs) {
    		render = renderManager.getRenderFactory().getJsonRender(attrs);
    	}
    	
    	/**
    	 * Render with json text.
    	 * <p>
    	 * Example: renderJson("{"message":"Please input password!"}");
    	 */
    	public void renderJson(String jsonText) {
    		render = renderManager.getRenderFactory().getJsonRender(jsonText);
    	}
    	
    	/**
    	 * Render json with object.
    	 * <p>
    	 * Example: renderJson(new User().set("name", "JFinal").set("age", 18));
    	 */
    	public void renderJson(Object object) {
    		render = object instanceof JsonRender ? (JsonRender)object : renderManager.getRenderFactory().getJsonRender(object);
    	}
    	
    	/**
    	 * Render with text. The contentType is: "text/plain".
    	 */
    	public void renderText(String text) {
    		render = renderManager.getRenderFactory().getTextRender(text);
    	}
    	
    	/**
    	 * Render with text and content type.
    	 * <p>
    	 * Example: renderText("&lt;user id='5888'&gt;James&lt;/user&gt;", "application/xml");
    	 */
    	public void renderText(String text, String contentType) {
    		render = renderManager.getRenderFactory().getTextRender(text, contentType);
    	}
    	
    	/**
    	 * Render with text and ContentType.
    	 * <p>
    	 * Example: renderText("&lt;html&gt;Hello James&lt;/html&gt;", ContentType.HTML);
    	 */
    	public void renderText(String text, ContentType contentType) {
    		render = renderManager.getRenderFactory().getTextRender(text, contentType);
    	}
    	
    	/**
    	 * Forward to an action
    	 */
    	public void forwardAction(String actionUrl) {
    		render = new ForwardActionRender(actionUrl);
    	}
    	
    	/**
    	 * Render with file
    	 */
    	public void renderFile(String fileName) {
    		render = renderManager.getRenderFactory().getFileRender(fileName);
    	}
    	
    	/**
    	 * Render with file, using the new file name to the client
    	 */
    	public void renderFile(String fileName, String downloadFileName) {
    		render = renderManager.getRenderFactory().getFileRender(fileName, downloadFileName);
    	}
    	
    	/**
    	 * Render with file
    	 */
    	public void renderFile(File file) {
    		render = renderManager.getRenderFactory().getFileRender(file);
    	}
    	
    	/**
    	 * Render with file, using the new file name to the client
    	 */
    	public void renderFile(File file, String downloadFileName) {
    		render = renderManager.getRenderFactory().getFileRender(file, downloadFileName);
    	}
    	
    	/**
    	 * Redirect to url
    	 */
    	public void redirect(String url) {
    		render = renderManager.getRenderFactory().getRedirectRender(url);
    	}
    	
    	/**
    	 * Redirect to url
    	 */
    	public void redirect(String url, boolean withQueryString) {
    		render = renderManager.getRenderFactory().getRedirectRender(url, withQueryString);
    	}
    	
    	/**
    	 * Render with view and status use default type Render configured in JFinalConfig
    	 */
    	public void render(String view, int status) {
    		render = renderManager.getRenderFactory().getRender(view);
    		response.setStatus(status);
    	}
    	
    	/**
    	 * Render with url and 301 status
    	 */
    	public void redirect301(String url) {
    		render = renderManager.getRenderFactory().getRedirect301Render(url);
    	}
    	
    	/**
    	 * Render with url and 301 status
    	 */
    	public void redirect301(String url, boolean withQueryString) {
    		render = renderManager.getRenderFactory().getRedirect301Render(url, withQueryString);
    	}
    	
    	/**
    	 * Render with view and errorCode status
    	 */
    	public void renderError(int errorCode, String view) {
    		throw new ActionException(errorCode, renderManager.getRenderFactory().getErrorRender(errorCode, view));
    	}
    	
    	/**
    	 * Render with render and errorCode status
    	 */
    	public void renderError(int errorCode, Render render) {
    		throw new ActionException(errorCode, render);
    	}
    	
    	/**
    	 * Render with view and errorCode status configured in JFinalConfig
    	 */
    	public void renderError(int errorCode) {
    		throw new ActionException(errorCode, renderManager.getRenderFactory().getErrorRender(errorCode));
    	}
    	
    	/**
    	 * Render nothing, no response to browser
    	 */
    	public void renderNull() {
    		render = renderManager.getRenderFactory().getNullRender();
    	}
    	
    	/**
    	 * Render with javascript text. The contentType is: "text/javascript".
    	 */
    	public void renderJavascript(String javascriptText) {
    		render = renderManager.getRenderFactory().getJavascriptRender(javascriptText);
    	}
    	
    	/**
    	 * Render with html text. The contentType is: "text/html".
    	 */
    	public void renderHtml(String htmlText) {
    		render = renderManager.getRenderFactory().getHtmlRender(htmlText);
    	}
    	
    	/**
    	 * Render with xml view using freemarker.
    	 */
    	public void renderXml(String view) {
    		render = renderManager.getRenderFactory().getXmlRender(view);
    	}
    	
    	public void renderCaptcha() {
    		render = renderManager.getRenderFactory().getCaptchaRender();
    	}
    	
    	/**
    	 * 渲染二维码
    	 * @param content 二维码中所包含的数据内容
    	 * @param width 二维码宽度,单位为像素
    	 * @param height 二维码高度,单位为像素
    	 */
    	public void renderQrCode(String content, int width, int height) {
    		render = renderManager.getRenderFactory().getQrCodeRender(content, width, height);
    	}
    	
    	/**
    	 * 渲染二维码,并指定纠错级别
    	 * @param content 二维码中所包含的数据内容
    	 * @param width 二维码宽度,单位为像素
    	 * @param height 二维码高度,单位为像素
    	 * @param errorCorrectionLevel 纠错级别,可设置的值从高到低分别为:'H'、'Q'、'M'、'L',具体的纠错能力如下:
    	 *  H = ~30% 
    	 *  Q = ~25%
    	 *  M = ~15%
    	 *  L = ~7%
    	 */
    	public void renderQrCode(String content, int width, int height, char errorCorrectionLevel) {
    		render = renderManager.getRenderFactory().getQrCodeRender(content, width, height, errorCorrectionLevel);
    	}
    	
    	public boolean validateCaptcha(String paraName) {
    		return com.jfinal.captcha.CaptchaRender.validate(this, getPara(paraName));
    	}
    

    这种改进的抽象工厂方法的好处在于:

    1.易于交换产品系列。

    由于具体工厂类,例如IRenderFactory renderFactory=new TemplateRenderFactory(); 在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。

    2.让具体的创建实例过程与客户端分离。

    客户端是通过它们的抽象接口操作实例,产品实现类的具体类名也被具体的工厂实现类分离,不会出现在客户端代码中。就像我们上面的例子,客户端只需要知道RenderManger,至于它是什么ViewType它就不知道了。

    3.简化了扩展功能代码。

    如果需要扩展Render的功能,只需要通过调用以下代码即可实现:

    
    	/**
    	 * Set the renderFactory
    	 */
    	public void setRenderFactory(IRenderFactory renderFactory) {
    		if (renderFactory == null) {
    			throw new IllegalArgumentException("renderFactory can not be null.");
    		}
    		RenderManager.me().setRenderFactory(renderFactory);
    	}
    
  • 相关阅读:
    awk常用命令
    Linux 指令篇:使用者管理--sudo
    sax解析xml案例一
    DefaultHandler类
    Linux上vi(vim)编辑器使用教程
    SecureCRT上传下载数据的方法
    K近邻的决策边界以及K的影响
    KNN交叉验证,找出合适的K值
    KNN(K邻近值算法)手动版与库函数调用版
    linear_model.LinearRegression()线性回归之身高预测体重
  • 原文地址:https://www.cnblogs.com/Erma/p/10401418.html
Copyright © 2011-2022 走看看