模板方法模式VS建造者模式!!!
二话不多,先学完在比较!!!
1.模板模式
定义:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤。
看完定义后,有点烦躁。。上例子!!
相信大家都去过星巴克喝东西吧。有茶,也有咖啡。
那先看看冲咖啡的步骤
- ① 把水煮沸
- ② 用沸水冲泡咖啡
- ③ 把咖啡倒进杯子里
- ④ 加糖和牛奶
在看看冲茶的步骤
- ① 把水煮沸
- ② 用沸水冲泡茶叶
- ③ 把茶水倒进杯子里
- ④ 加柠檬
大家发现了没有步骤都是类似的。。而我们去星巴克点东西的时候,里面的工作人员就按照这里的步骤给我们冲咖啡(茶)!!而且每一个人都是一样的步骤。
代码如下:
/**
* 模板!!!
*
* @constructor
*/
var CaffeineBeverage = function() {
this._prepareRecipe = function() {
this.boilWater();
this.brew();
this.pourInCup();
this.addCondiments();
};
this.boilWater = function() {
console.log('烧水!!');
};
this.pourInCup = function() {
console.log('倒进杯子里面!');
};
this.brew = function() {
throw new Error('子类实现');
};
this.addCondiments = function() {
throw new Error('子类实现');
};
};
/**
* 冲茶的实现
*
* @constructor
*/
var TeaWithHold = function() {};
TeaWithHold.prototype = new CaffeineBeverage();
TeaWithHold.prototype.brew = function() {
console.log('冲茶!!');
};
TeaWithHold.prototype.addCondiments = function() {
console.log('加柠檬!!');
};
/**
* 冲咖啡的实现
*
* @constructor
*/
var CoffeeWithHold = function() {};
CoffeeWithHold.prototype = new CaffeineBeverage();
CoffeeWithHold.prototype.brew = function() {
console.log('冲咖啡!!');
};
CoffeeWithHold.prototype.addCondiments = function() {
console.log('加牛奶和糖!!');
};
// 运行
var teaWithHold = new TeaWithHold();
teaWithHold._prepareRecipe();
var coffeeWithHold = new CoffeeWithHold();
coffeeWithHold._prepareRecipe();
运行结果
到了这里模板模式应该学会了吧,嘻嘻。。没玩呢!!继续!!
2.建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
适用性
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
参与者
1.Builder 为创建一个Product对象的各个部件指定抽象接口。2.ConcreteBuilder 实现Builder的接口以构造和装配该产品的各个部件。 定义并明确它所创建的表示。 提供一个检索产品的接口。
3.Director 构造一个使用Builder接口的对象。
4.Product 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
- 再来一张 uml 图
好吧,我知道,不少人已经开骂了,把七八糟的看的头晕。。
我先简单说一下这个模式。有过游戏的人都知道,创建角色的时候有男性和女性吧,有的游戏直接还可以选择角色头发的颜色啊,外观,衣服,鞋子之类的。然后创建角色的袋盖步骤就是:
- 创建角色
- 设置头的参数(头发的颜色,眼睛大小等等)
- 设置身体的参数(什么衣服,衣服颜色,饰品)
- 设置脚的参数(鞋子等等)
发现了没有!!和模板差不多吧,没错就是很像,不过只是像!!
先看代码!!
/**
* 以下代码属于 Product 部分
*
* @constructor
*/
var Person = function() {
this.head = '';
this.body = '';
this.foot = '';
this.setFoot = function(f) {
this.foot = f;
};
this.setBody = function(b) {
this.body = b;
};
this.setHead = function(h) {
this.head = h;
};
// 省略 getter
};
var WomanPerson = function() {
this.sex = 0;
// setter getter 省略
};
WomanPerson.prototype = new Person();
var ManPerson = function() {
this.sex = 1;
// setter getter 省略
};
ManPerson.prototype = new Person();
/**
* 人类创建基类 Builder接口
* (由于js没有接口,所以这里利用类作为Builder)
*
* @constructor
*/
var PersonBuilder = function() {
this.buildHead = function() {};
this.buildBody = function() {};
this.buildFoot = function() {};
this.buildPerson = function() {};
};
/**
* 男人生成器
*
* @constructor
*/
var ManPersonBuilder = function() {
this.person = new ManPerson();
};
ManPersonBuilder.prototype = new PersonBuilder();
ManPersonBuilder.prototype.buildHead = function() {
this.person.setHead('man head');
};
ManPersonBuilder.prototype.buildBody = function() {
this.person.setBody('man body');
};
ManPersonBuilder.prototype.buildFoot = function() {
this.person.setFoot('man foot');
};
ManPersonBuilder.prototype.buildPerson = function() {
return this.person;
};
// 女生生成器类似,不写了
/**
* Director
* 通过不同的Builder,创建不同的人,也就是Product
*
* @constructor
*/
var PersonDirector = function() {
this.constructPerson = function(pb) {
pb.buildHead();
pb.buildBody();
pb.buildFoot();
return pb.buildPerson();
};
};
// 运行
var director = new PersonDirector();
var manPerson = director.constructPerson(new ManPersonBuilder()); // 大家请看这里!!
console.log(manPerson.head + ' -- ' + manPerson.body + ' -- ' + manPerson.foot);
看完代码,发现了没有,算法的结构不是写在父类继承来的,而建造者模式是通过组合的方式运行的(看我代码注释“大家请看这里!!”的那一行。熟悉设计模式的朋友就会发现,有策略模式的影子!)。而是Director里面的。另外,有返回对象,而模板模式没有。或者这么说吧,建造者模式注重的创建,模板注重的是行为。
当然啦,这些是我个人的总结,网上有很多比我更加专业的说法,什么行为型模式设计到算法和对象间的职责分配,不仅描述对象或类的模式,还描述它们之间的通信方式,刻划了运行时难以跟踪的复杂的控制流,它们将你的注意力从控制流转移到对象间的关系上来。#%&*%#(这句话是网上抄来的。省略N个字,大家如果想要更专业的描述,找度娘,很多大神比我写的更加专业)