创建型设计模式
创建型设计模式
简创建型设计设计模式主要是在于创建,如何将创建和使用两种行为分离是这种设计模式的中心思想。创建型设计模式能够有效地降低系统耦合度,作为使用者,不需要去关心对象的创建细节,创建的这个过程由相关的工厂完成。创建型设计模式分为以下几种:
- 单例模式。这种类只会生成一个实例
- 原型模式。将一个对象作为原型,可以讲其复制或克隆出多个原型类型的不同实例
- 工厂方法。提供就一个方法,根据参数生成不同的实例
- 抽象工厂模式。提供一个创建产品族的接口,其每个子类可以生产一些列相关的产品。
- 建造者模式。拆解然后拼装,将复杂的对象拆解成多个简单属性,然后根据不同的需求进行拼装成不同的复杂对象。
简单工厂模式
简单工厂模式就是不用手动去针对不同类型的相似对象去手动创建类,而是把这个创建类的过程交由JavaScript来帮你创建,你只需要告诉这个工厂方法你需要创建什么样的类就行了。
function Factory(type) { // 工厂方法
function Ball() {
this.name = 'ball'
this.user = 'palyer'
}
function Book() {
this.name = 'book'
}
switch(type) {
case 'book':
return new Book()
case 'ball':
return new Ball()
}
}
var book1 = Factory('book')
var ball1 = Factory('ball')
如果有很多相似的属性或者方法,可以先抽象出他们共同的相似部分,然后再根据特殊的情况创建特殊属性方法。
function Factory(type, name) { // 工厂方法
var i = new Object()
i.name = name
switch(type) {
case 'book':
i.user = 'palyer'
case 'ball':
i.reader = 'everybody'
}
return i
}
第一种是通过实例化对象来创建的,第二种是通过创建一个新对象然后包装增强其属性和功能来实现的。他们之间的差异性也造成前面通过类创建的对象,如果这些类继承同一父类,那么他们的父类原型上的方法是公用的。而后面寄生方式创建的对象都是一个新的个体,所以他们的方法就不能共用了。
工厂方法模式
工厂方法模式:通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例
安全模式类
安全模式类就是通过判断一次this的指向来判断调用者是通过new关键来实例化对象还是直接当做function来使用
if (!(this instanceof SafeClass)) {
return new SafeClass();
}
}
SafeClass.prototype.say = function() {
// do something
}
var test = SafeClass()
test.say() // 能够访问say()方法
这样即便是使用var test = SafeClass()这样直接调用方法的方式也能得到一个SafeClass类
安全的工厂方法
对于创建多类对象,简单工厂模式就不太适用了,通过工厂方法模式可以创建多个类的实例对象,而且工厂方法在创建对象的方式也避免了使用者与对象类之间的耦合,不用关心创建该对象的具体类,只需要调用工厂方法即可。
var Factory = function(type, name) {
if (this instanceof Factory) { // 如果是通过关键字new来实例化的
var s = new this[type](name)
return s
} else {
return new Factory(type, name)
}
}
Factory.prototype.Book = function(name) {
this.name = name
}
Factory.prototype.Ball = function(name) {
this.name = name
}
var book = Factory('Book', 'book')
var ball = new Factory('Ball', 'ball')
抽象工厂模式
抽象工厂模式:通过对类的工厂抽象使其业务用于对产品类簇的创建,而不负责创建某一类的实例。
抽象类
抽象类就是能被声明但是不能被使用的类。JavaScript中不能直接创建抽象类,但是可以通过抛出错误来创建一个抽象类,如果直接使用抽象类中的方法则会抛出错误,必须在子类中重写该方法才能正确使用。
var AbsClass = function(){}
AbsClass.prototype.sleep = function() {
return new Error('这是抽象类不能被直接使用')
}
var abs = new AbsClass()
console.log(abs.sleep()) // Error: 这是抽象类不能被直接使用
抽象工厂类方法
var VehicleFactory = function (subClass, superClass) {
// 判断抽象工厂中是否有该抽象类
if (typeof VehicleFactory[superClass] === 'function') {
// 创建一个缓存类
function F() {
}
// 继承父类的属性方法
F.prototype = new VehicleFactory[superClass]()
// 修正subClass的constructor指向
subClass.constructor = subClass
// 子类原型继承父类
subClass.prototype = new F()
} else {
throw new Error(‘未创建该抽象类
')
}
}
VehicleFactory.Book = function () {
this.type = 'book'
}
VehicleFactory.Book.prototype = {
getPrice: function () {
return new Error('抽象类方法不能调用')
}
}
var JsBook = function () {
this.price = '100元';
}
VehicleFactory(JsBook, 'Book')
JsBook.prototype.getPrice = function () {
return this.price
}
var js1 = new JsBook()
console.log(js1.getPrice()) // 100元
VehicleFactory方法需要传递子类已经要继承父类的名称,并且在抽象工厂方法中又增加了一次对抽象类存在性的一次判断,如果存在抽象类则开始继承抽象类,否则抛出一个错误。继承父类的过程中有一个地方需要值得注意,就是在对过度类的原型继承时,继承的不是父类的原型,而是通过new关键字复制的父类的一个实例,这么做是因为过度类不仅应该继承父类的原型方法还要继承父类的属性对象。但是由于实际被实例化的是子类,因此需要将子类的constructor属性修正指向到子类身上。
建造者模式
建造者模式将一个复杂对象的构建层与其表现层相互分离,同样的构建过程可采用不同的表示。工厂模式主要是为了创建对象实例或者类簇(抽象工厂),关心的是最终产出的是什么,不关心你创建的整个过程。而建造者模式在创建对象的时候要复杂一些,对染其目的也是为了创建对象,但是它更关心的是创建这个对象的整个过程,建造者模式更注重的是创建的细节。
// 建造者模式就是在类中创建一个类,这个类的属性又是其他类的实例对象
var Human = function (parma) {
this.skill = parma && parma.skill || '保密'
this.hobby = parma && parma.hobby || '保密'
}
Human.prototype.getSkils = function () {
return this.skill
}
Human.prototype.getHobby = function () {
return this.hobby
}
var Named = function (name) {
var that = this;
(function (name, that) {
var wholeName = name
if (name.indexOf(' ') > -1) {
that.firstName = name.slice(0, name.indexOf(' '))
that.lastName = name.slice(name.indexOf(' ') + 1)
}
})(name, that)
}
var Work = function (work) {
var that = this;
(function (work, that) {
switch (work) {
case 'teacher':
that.work = '教师'
that.workDis = '这是教师职业'
break
case 'coder':
that.work = '码农'
that.workDis = '敲代码敲到死'
break
default:
that.work = work
that.workDis = '暂无描述'
}
})(work, that)
}
Work.prototype.changeWork = function (work) {
this.work = work
}
Work.prototype.changeWorkDis = function (dis) {
this.workDis = dis
}
// 建造者类
function Creater(name, work, parma) {
var _p = new Human(parma) // 缓存一个Human实例
_p.name = new Named(name)
_p.hopeWork = new Work(work)
return _p
}
var p1 = new Creater('zheng xinglun', 'coder', {
skill: 'js'
})
console.log(p1.getSkils()) // js
console.log(p1.hopeWork.workDis) // '敲代码敲到死'
p1.hopeWork.changeWork('teacher')
console.log(p1.hopeWork.work) // 'teacher'
工厂模式创建出来的是一个对象,它追求的是创建的结果,仅仅是一个实实在在的创建过程。而建造者模式不仅仅可以得到创建的结果,而且也参与了创建的具体过程,建造者模式就是在建造一个可以自定义的工厂。细化各种类,然后通过建造者模式来拼装成一个完整的产品类。