深入学习js之浅谈设计模式(行为委托)

js的本质是对象之间的关联关系

1.比较面向对象和对象关联的设计模式

面向对象

function Foo(who) {
				this.me = who;
			}
			Foo.prototype.identify = function () {
				return "I am " + this.me;
			};

			function Bar(who) {
				Foo.call(this,who);
			}
			Bar.prototype = Object.create( Foo.prototype );

			Bar.prototype.speak = function () {
				alert("Hello, " + this.identify() + ".");
			};

			var b1 = new Bar("b1");
			var b2 = new Bar("b2");

			b1.speak();
			b2.speak();
子类Bar继承了父类Foo,然后生成了b1和b2两个实例。b1委托了Bar.prototype,Bar。prototype委托了Foo.prototype。


关联模式:

Foo = {
				init: function (who) {
					this.me = who;
				},
				identify: function () {
					return "I am " + this.me;
				}
			};

			Bar = Object.create( Foo );

			Bar.speak = function () {
				alert( "Hello, " + this.identify() + "." );
			};

			var b1 = Object.create(Bar);
			b1.init("b1");
			var b2 = Object.create(Bar);
			b2.init("b2");

			b1.speak();
			b2.speak();

通过比较可以看出,对象关联风格的代码显得更加简洁,因为这种代码只关注一件事情:对象之间的关联关系。

结合一下前端的常用使用场景,下面用控件类举例

类风格代码:

function Widget(width,height) {
				this.width = width || 50;
				this.height = height || 50;
				this.elem = null;
			}

			Widget.prototype.render = function (where) {
				if (this.elem) {
					this.elem.css({
						width: this.width + 'px',
						height: this.height + 'px'
					}).appendTo(where);
				}
			};

			//子类
			function Button(width,height,label) {
				//调用super构造函数
				Widget.call(this, width, height);
				this.lable = label || "Default";

				this.elem = $("

在面向对象设计模式中我们需要先在父类中定义基础的render,然后再子类中重写它。子类并不会替换基础的render,只是添加一些按钮特有的行为。

可以看到代码中出现了显式伪多态,即通过Widget.call和Widget.prototype.render.call从子类方法中引用父类中的基础方法。

ES6的class语法糖

class Widget{
				constructor(width,height) {
					this.width = width || 50;
					this.height = height || 50;
					this.elem = null;
				}
				render(where) {
					if (this.elem) {
						this.elem.css({
							width: this.width + 'px',
							height: this.height + 'px'
						}).append(where);
					}
				}
			}

			class Button extends Widget {
				constructor(width,height,label){
					super(width,height);
					this.label = label || "Default";
					this.elem = $( "

可以看出在语法简洁上做出了很大改进,以及super的调用


委托控件对象

var Widget = {
				init:function (width,height) {
					this.width = width || 50;
					this.height = height || 50;
					this.elem = null;
				},
				insert: function (where) {
					if (this.elem) {
						this.elem.css({
							width: this.width + 'px',
							height: this.height + 'px'
						}).append(where);
					}
				}
			};

			var Button = Object.create(Widget);

			Button.setup = function (width,height,label) {
				//委托调用
				this.init( width, height );
				this.label = label || "Default";

				this.elem = $("
使用对象关联风格来编写代码时,不需要把Widget和Button当作父类和子类。相反,Widget只是一个对象,包含一组通用的函数,任何类型的控件都可以委托,Button同样只是一个对象。(它通过委托关联到Widget)

从设计模式的角度看,我们并没有像类一样在两个对象中都定义相同的方法名render,而是两个更加具体描述性的方法名。

在委托设计模式中,除了使用不相同的方法名外,还要通过对象关联避免丑陋的显式伪多态调用(Widget.call....),代之以简单的相对委托调用this.init()和this.insert()

 从语法角度来说,我们同样没有使用任何构造函数、.prototype或new


小结:

行为委托认为对象之间是兄弟关系,互相委托,而不是父类和子类的关系。js机制的本质上就是行为委托机制。

对象关联是一种编码风格,它倡导的是直接创建和关联对象,不拔它们抽象成类。对象关联可以用基于[[prototype]]的行为委托非常自然的实现

你可能感兴趣的:(----------前端开发,javascript)