JS设计模式之组合模式

       组合模式就是指在页面表现中,通过一条指令而达到在多个对象中的复杂的递归行为,就是通过控制一个对象,不过该对象复杂的递归下去又是很多复杂的对象,同时控制对象的行为。这样简化代码,可维护,复杂的对象的行为委托给一个对象。

      组合模式确实能对于工作能起到简化作用,组合对象实现某一操作时,通过递归,向下传递到所有的组成对象,在存在大批对象时,假如页面的包含许多拥有同样功能的对象,只需要操作组合对象即可达到目标。在存在存在着某种的层次结构,并且其中的一部分要实现某些操作,即可使用组合模式。

    下面是组合模式书上的例子,展示了表单验证与图片阅读器。

        表单验证中,需要做的工作是表单的保存、恢复和验证表单中的值,然而表单的数量是未知数,类型是未知数,只有功能能确定的情况下,使用组合模式无疑最好,通过给每个表单添加功能,然后一个表单对象组合起来,通过操作表单对象即可达到操作表单。

        图片阅读器与表单验证基本一样,通过汇合操作图片。

<!DOCTYPE HTML>
<html>
<head>
<style>
</style>

</head>
<body>
	<input value="存储" type="button" οnclick="a()" />
	<input value="取出" type="button" οnclick="b()" />
	<input value="隐藏" type="button" οnclick="c()" />
	<input value="显示" type="button" οnclick="d()" />
</body>
<script type="text/javascript">
    //存储的值  
	var value_content = {};
	function setCookie(name, value) {
		value_content[name] = value;
	}
	function getCookie(name) {
		return value_content[name];
	}
    //表单组合对象
	var CompositeForm = function(id, method, action) {
		this.formComponents = [];

		this.element = document.createElement('form');
		this.element.id = id;
		this.element.method = method || 'POST';
		this.element.action = action || '#';
	}
    
	CompositeForm.prototype.add = function(child) {
		this.formComponents.push(child);
		this.element.appendChild(child.getElement());
	}
	CompositeForm.prototype.remove = function(child) {
		for ( var i = 0, len = this.formComponents.length; i < len; i++) {
			if (child == this.formComponents[i]) {
				this.formComponents.splice(i, 1);
				break;
			}
		}
	}
	CompositeForm.prototype.getChild = function(i) {
		return this.formComponents[i];
	}
	
	CompositeForm.prototype.save = function() {
		for ( var i = 0, len = this.formComponents.length; i < len; i++) {
			this.formComponents[i].save();
		}
	}
	CompositeForm.prototype.restore = function() {
		for ( var i = 0, len = this.formComponents.length; i < len; i++) {
			this.formComponents[i].restore();
		}
	}
	CompositeForm.prototype.getElement = function() {
		return this.element;
	}
    //接口方法
	var Field = function(id) {
		this.id = id;
		this.element;
		this.content;
	};
	Field.prototype.add = function() {
	};
	Field.prototype.remove = function() {
	};
	Field.prototype.getChild = function() {
	};

	Field.prototype.save = function() {
		setCookie(this.id, this.getValue());
	};
	Field.prototype.getElement = function() {
		return this.element;
	}
	Field.prototype.getValue = function() {
		throw new Error('错误');
	}
	Field.prototype.restore = function() {
		this.content.value = getCookie(this.id);
	};
    //继承方法
	function extend(subClass, superClass) {
		var F = function() {
		};
		F.prototype = superClass.prototype;
		subClass.prototype = new F();
		subClass.prototype.constructor = subClass;

		subClass.superclass = superClass.prototype;
		if (superClass.prototype.constructor == Object.prototype.constructor) {
			superClass.prototype.constructor = superClass;
		}
	}
    //输入框
	var InputField = function(id, label) {
		Field.call(this, id);

		this.input = document.createElement('input');
		this.content = this.input;

		this.label = document.createElement('label');
		var labelTextNode = document.createTextNode(label);
		this.label.appendChild(labelTextNode);

		this.element = document.createElement('div');
		this.element.id = id;
		this.element.className = 'input-field';
		this.element.appendChild(this.label);
		this.element.appendChild(this.input);
	}
	extend(InputField, Field);
	InputField.prototype.getValue = function() {
		return this.input.value;
	};
    //文本框
	var TextareaField = function(id, label) {
		Field.call(this, id);

		this.textarea = document.createElement('textarea');
		this.content = this.textarea;

		this.label = document.createElement('label');
		var labelTextNode = document.createTextNode(label);
		this.label.appendChild(labelTextNode);

		this.element = document.createElement('div');
		this.element.id = id;
		this.element.className = 'input-field';
		this.element.appendChild(this.label);
		this.element.appendChild(this.textarea);
	};
	extend(TextareaField, Field);
	TextareaField.prototype.getValue = function() {
		return this.textarea.value;
	};
    //选择框
	var SelectField = function(id, label) {
		Field.call(this, id);

		this.select = document.createElement('select');
		this.select.options.add(new Option("sfs", "sfs"));
		this.select.options.add(new Option("111", "2222222222")); //这边value会改变
		this.content = this.select;

		this.label = document.createElement('label');
		var labelTextNode = document.createTextNode(label);
		this.label.appendChild(labelTextNode);

		this.element = document.createElement('div');
		this.element.id = id;
		this.element.className = 'input-field';
		this.element.appendChild(this.label);
		this.element.appendChild(this.select);
	};
	extend(SelectField, Field);
	SelectField.prototype.getValue = function() {
		return this.select.options[this.select.options.selectedIndex].value;
	};
    //表单域
	var CompositeFieldset = function(id, legendText) {
		this.components = {};

		this.element = document.createElement('fieldset');
		this.element.id = id;

		if (legendText) {
			this.legend = document.createElement('legend');
			this.legend.appendChild(document.createTextNode(legendText));
			this.element.appendChild(this.legend);
		}
	};

	CompositeFieldset.prototype.add = function(child) {
		this.components[child.getElement().id] = child;
		this.element.appendChild(child.getElement());
	};

	CompositeFieldset.prototype.remove = function(child) {
		delete this.components[child.getElement().id];
	};

	CompositeFieldset.prototype.getChild = function(id) {
		if (this.components[id] != undefined) {
			return this.components[id];
		} else {
			return null;
		}
	};

	CompositeFieldset.prototype.save = function() {
		for ( var id in this.components) {
			if (!this.components.hasOwnProperty(id))
				continue;
			this.components[id].save();
		}
	};

	CompositeFieldset.prototype.restore = function() {
		for ( var id in this.components) {
			if (!this.components.hasOwnProperty(id))
				continue;
			this.components[id].restore();
		}
	};

	CompositeFieldset.prototype.getElement = function() {
		return this.element;
	};

	//组合模式开始
	/*  var contactForm=new CompositeForm('contact-form','POST','test');
	
	 contactForm.add(new InputField('first-name','First Name'));
	 contactForm.add(new InputField('last-name','Last Name'));
	 contactForm.add(new InputField('address','Address'));
	 contactForm.add(new InputField('city','City'));
	 var stateArray=[];
	 contactForm.add(new SelectField('state','State',stateArray));
	 contactForm.add(new InputField('zip','Zip'));
	 contactForm.add(new TextareaField('comments','Comments'));
	
	 contactForm.save(); */

    //用组合模式汇合起来
	var contactForm = new CompositeForm('contact-form', 'POST', 'test');

	var nameFieldset = new CompositeFieldset('name-fieldset');
	nameFieldset.add(new InputField('first-name', 'First Name'));
	nameFieldset.add(new InputField('last-name', 'Last Name'));
	contactForm.add(nameFieldset);

	var addressFieldset = new CompositeFieldset('address-fieldset');
	addressFieldset.add(new InputField('address', 'Address'));
	addressFieldset.add(new InputField('city', 'City'));
	addressFieldset.add(new SelectField('state', 'State'));
	addressFieldset.add(new InputField('zip', 'Zip'));
	contactForm.add(addressFieldset);

	contactForm.add(new TextareaField('comments', 'Comments'));

	document.body.appendChild(contactForm.getElement());

	function a() {
		contactForm.save();
	}
	function b() {
		contactForm.restore();
	}
	//图片库
	var DynamicGallery=function(id){
		this.children=[];
		
		this.element=document.createElement('div');
		this.element.id=id;
		this.element.className='dynamic-gallery';
	};
	DynamicGallery.prototype={
		add:function(child){
			this.children.push(child);
			this.element.appendChild(child.getElement());
		},
		remove:function(child){
			for(var node,i=0;node=this.getChild(i);i++){
				if(node==child){
					this.children.splice(i,1);
					break;
				}
			}
			this.element.removeChild(chld.getElement());
		},
		getChild:function(i){
			return this.children[i];
		},
		hide:function(){
			for(var i=0,node;node=this.getChild(i);i++){
				node.hide();
			}
			this.element.style.display='none';
		},
		show:function(){
			this.element.style.display='block';
			for(var i=0,node;node=this.getChild(i);i++){
				node.show();
			}
		},
		getElement:function(){
			return this.element;
		}
	};
	
	//单个图片
	var GalleryImage=function(src){
		this.element=document.createElement('img');
		this.element.className='gallery-image';
		this.element.src=src;
	};
	GalleryImage.prototype={
		add:function(){},
		remove:function(){},
		getChild:function(){},
		hide:function(){
			this.element.style.display='none';
		},
		show:function(){
			this.element.style.display='';
		},
		getElement:function(){
			return this.element;
		}
	};
	//汇合起来
	var topGallery=new DynamicGallery('top-gallery');
	topGallery.add(new GalleryImage('img/abc1.jpg'));
	topGallery.add(new GalleryImage('img/abc2.jpg'));
	topGallery.add(new GalleryImage('img/abc3.jpg'));
	
	var vacationPhotos=new DynamicGallery('vacation-photos');
	for(var p=0;p<30;p++){
		vacationPhotos.add(new GalleryImage('img/abc3.jpg'));
	}
	topGallery.add(vacationPhotos);
	document.body.appendChild(topGallery.getElement());
	function c(){
		topGallery.hide();
	}
	function d(){
		topGallery.show();
	}
</script>
</html>
组合模式通过简单的操作就能达到复杂的效果,一个操作通过遍历递归传递这个操作。不过组合模式的弱点也在于此,如果层次过多,则性能将受到影响。

组合模式应用场所  应用在对一批对象具有相同的动作的情况下适用,并产生递归的条件下。即是符合两个条件,一是产生递归,二是具有相同的动作。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值