The visitor visitor design pattern in the SAP Fiori Elements application

SAP Fiori Elements applies the text property of the SmartTable title control, how is it generated at runtime?

Set a breakpoint in TitleRenderer.js:

Call getText to get the text property value:

The question is where does this Text property come from?

Inside SmartTable.jscan observe this Products string:

The final entry is still XMLTemplateProcessor.js:

It should be triggered by these XML fragment loading:

Download smarttable.fragment.xml locally and open it to observe its header binding information:

{= !${parameter>/settings/quickVariantSelection/showCounts} ? ${path: 'header>TypeNamePlural', formatter: 'sap.ui.model.odata.AnnotationHelper.format'} : '' }

TypeNamePluralSearch by keyword :

Breakpoints are set, none are triggered.
PropertyBinding:

A visitor pattern:

source code:

/**
			 * Visits the given attribute of the given element. If the attribute value represents a
			 * binding expression that can be resolved, it is replaced with the resulting value.
			 *
			 * @param {Element} oElement the XML DOM element
			 * @param {Attr} oAttribute one of the element's attribute nodes
			 * @param {sap.ui.core.template._with} oWithControl the "with" control
			 * @returns {sap.ui.base.SyncPromise}
			 *   A sync promise which resolves with <code>undefined</code> as soon as the
			 *   attribute's value has been replaced, or is rejected with a corresponding error if
			 *   getting the binding's value fails.
			 */
			function visitAttribute(oElement, oAttribute, oWithControl) {
    
    
				if (fnSupportInfo) {
    
    
					fnSupportInfo({
    
    context:undefined /*context from node clone*/, env:{
    
    caller:"visitAttribute", before: {
    
    name: oAttribute.name, value: oAttribute.value}}});
				}
				return resolveAttributeBinding(oElement, oAttribute, oWithControl)
					.then(function () {
    
    
						if (fnSupportInfo) {
    
    
							fnSupportInfo({
    
    context:undefined /*context from node clone*/, env:{
    
    caller:"visitAttribute", after: {
    
    name: oAttribute.name, value: oAttribute.value}}});
						}
					});
			}

			/**
			 * Visits all attributes of the given element. If an attribute value represents a
			 * binding expression that can be resolved, it is replaced with the resulting value.
			 *
			 * @param {Element} oElement the XML DOM element
			 * @param {sap.ui.core.template._with} oWithControl the "with" control
			 * @returns {sap.ui.base.SyncPromise}
			 *   A sync promise which resolves with <code>undefined</code> as soon as all
			 *   attributes' values have been replaced, or is rejected with a corresponding error if
			 *   getting some binding's value fails.
			 */
			function visitAttributes(oElement, oWithControl) {
    
    
				/*
				 * Comparator for DOM attributes by name.
				 *
				 * @param {Attr} oAttributeA
				 * @param {Attr} oAttributeB
				 * @returns {number} <0, 0, >0
				 */
				function comparator(oAttributeA, oAttributeB) {
    
    
					return oAttributeA.name.localeCompare(oAttributeB.name);
				}

				return stopAndGo(
					// Note: iterate over a shallow copy to account for removal of attributes!
					// Note: sort attributes by name to achieve a stable log order across browsers
					Array.prototype.slice.apply(oElement.attributes).sort(comparator),
					function (oAttribute) {
    
    
						return visitAttribute(oElement, oAttribute, oWithControl);
					});
			}

The design pattern used in this code is the Visitor pattern.

The visitor pattern is a design pattern that separates algorithms from object structure. This pattern defines a visit operation on an element in an object structure that takes as argument a visitor in which it implements an operation on the element.

In this code, the visitAttributeand visitAttributesfunction acts as the visitor. They access XML DOM elements and their attributes, resolve binding expressions that may exist in the attributes, and replace the original attribute values ​​with the parsed results.

For example, visitAttributea function accesses a single property, resolveAttributeBindingresolves possible binding expressions via , and asynchronously replaces property values ​​via a Promise structure. The function, on the other visitAttributeshand, accesses all attributes of the element, visitAttributeprocessing each attribute by calling .

This method of accessing and processing elements through visitors separates elements from processing logic, increasing the scalability and reusability of code. When new operations need to be performed on an element, only a new visitor needs to be defined without modifying the element class. At the same time, the visitor pattern also makes it easier to add new operations, just add a new visitor.

This code also embodies another feature of the visitor pattern, that is, the visitor can accumulate state. In this code, the visitor returns the processing result through the Promise structure, which can be regarded as the state accumulated by the visitor during the visit. Through the Promise structure, asynchronous operations and errors can be easily handled, which is also a common application of the visitor pattern.

Guess you like

Origin blog.csdn.net/i042416/article/details/131926540