创建类型设计模式包含原型模式
、构造模式
、工厂模式
、抽象工厂模式
、建造模式
、单例模式
,其中的工厂模式
和抽象工厂模式
因为设计理念类似,所以在很多文章中都会把它们统称为工厂模式
,工厂模式
又从服务目标的不同分为简单工厂模式
、工厂方法模式
、抽象工厂模式
在以前,因为工厂模式
更适合服务于面向对象语言,所有了在JS语言中被提到的时间会很少,学不学也就无关紧要了,但是随着TS语言的发展,面向对象模式又在前端兴起,所有还不趁现在抓紧学习起来!!!!
简单工厂模式
例子:去银行取钱
场景:在银行开设之初,取钱业务是通过用户直接去金库取钱而完成
// 取钱业务
class Take {
num: number
type: string
constructor(type: string, num: number) {
this.type = type
this.num = num
}
}
// 你直接金库取钱
let money50 = new Take('RMB', 50)
在银行开设一段时间后,发现了两个问题:
- 遇到不诚实的用户,本来他的银行卡里面只有50人民币,但是他却在金库取了50美元,银行亏损验证
- 遇到一些不熟悉取钱业务的用户,就根本不知道如何去取钱
为什么解决这两个问题,银行招收了一些业务员,专门为用户办理取钱业务
// 取钱业务
class Take {
num: number
type: string
constructor(type: string, num: number) {
this.type = type
this.num = num
}
}
// 业务员
class Salesman {
public static takeMoney(type, num): Take {
if (type === 'RMB') {
return new Take('RMB', num)
} else if (type === 'USD') {
return new Take('USD', num)
} else {
return new Take('RMB', num)
}
}
}
let money50 = Salesman.takeMoney('USD', 50)
在业务员的不懈努力下,不仅防止了用户乱取钱,还帮助许多不熟悉取钱业务的用户取钱,在这里业务员就是工厂类,他的存在就是为了控制金库类的创建和方便用户创建金库类
设计模式的原则是封装与隔离,简单工厂模式通过工厂类隔离类创建者和类,将类的创建逻辑封装在工厂类中,在例子中,Salesman类
就是工厂类,静态方法takeMoney
承担了创建了Take类
的职责
简单工厂模式的优点其实已经可以不言而喻了
- 保护类不被开发者胡乱创建(创建
Take类
时,第一个参数本应传递RMB
,开发者却传递USD
,想多取钱) - 方便开发者创建类(如果
Take类
需要接受100参数,那开发者不可能记住这100参数呀,而通过takeMoney
提前设置好这100个参数,开发者就可以方便创建对象了)
工厂方法模式
场景:银行现在不止需要开设取钱业务,还需要开设存钱、贷款业务
// 取钱业务
class Take {
num: number
type: string
constructor(type: string, num: number) {
this.type = type
this.num = num
}
}
// 贷款业务
class Loan {
num: number
type: string
constructor(type: string, num: number) {
this.type = type
this.num = num
}
}
// 业务员
class Salesman {
public static takeMoney(businessType, type, num): Take | Loan {
if (businessType === 'Take') {
if (type === 'RMB') {
return new Take('RMB', num)
} else if (type === 'USD') {
return new Take('USD', num)
} else {
return new Take('RMB', num)
}
} else if (businessType === 'Loan') {
if (type === 'RMB') {
return new Loan('RMB', num)
} else if (type === 'USD') {
return new Loan('USD', num)
} else {
return new Loan('RMB', num)
}
}
}
}
let money50 = Salesman.takeMoney('Take', 'USD', 50)
银行营业没几周,所有业务员都抗议,又出现问题了
- 他们觉得自己太累了,需要记住银行所以的业务,根本忙不过来
- 新增业务时,需要培训所以的业务员,变动很大
讲过会议商讨,决定根据业务的不同而设立不同的部门,将业务员分到不同的部门下面,再设立协助岗位(拿到用户的业务需求,然后去对应的部门办理业务)
interface Business {
num: number
type: string
}
interface BusinessConstructor {
new(type: string, num: number): Business;
}
// 取钱业务
class Take implements Business {
num: number
type: string
constructor(type: string, num: number) {
this.type = type
this.num = num
}
}
// 贷款业务
class Loan implements Business {
num: number
type: string
constructor(type: string, num: number) {
this.type = type
this.num = num
}
}
// 取钱部门
class TakeDepartment extends Take {
constructor(type, num) {
if (type === 'RMB') {
super('RMB', num)
} else if (type === 'USD') {
super('USD', num)
} else {
super('RMB', num)
}
}
}
// 贷款部门
class LoanDepartment extends Take {
constructor(type, num) {
if (type === 'RMB') {
super('RMB', num)
} else if (type === 'USD') {
super('USD', num)
} else {
super('RMB', num)
}
}
}
// 协助岗位
class Salesman {
public static takeMoney(businessType, ...args: ConstructorParameters<BusinessConstructor>): Take | Loan {
if (businessType === 'Take') {
return new TakeDepartment(...args)
} else if (businessType === 'Loan') {
return new LoanDepartment(...args)
}
}
}
let money50 = Salesman.takeMoney('Take', 'USD', 50,)
通过用户员和协助岗位的共通协做,业务实施的十分顺利,每个部门都只需要做自己的事情,而不需要关心其他部门的业务,大大减少了业务员的压力,而且再新增其他业务时,只需要添加对应的业务部门就可以了
工厂方法模式的核心是工厂类负责找到目标类的子类,实际创建对象的过程推迟由目标类的子类完成
,Salesman类
从业务员到协助岗位,实际上是,Salesman类
的工作中心由具体业务到寻找部门的过程,起着中间层的作用,而LoanDepartment
、TakeDepartment
这些部门子类则担起了完成业务的职责
工厂方法模式的优点也是很明显的
- 承上启下,利于业务扩建(以后再新增存钱业务,只用增加对应的部门和培训协助岗位就可以了)
- 单一职能,把具体业务分配到不同的子类中(取钱部门和贷款部门业务独立)
抽象工厂模式
场景:为了拓展义务,高层决定在每个部门都新增业务
在工厂方法模式中,一个部门只能实现一种业务,为了实现多种业务,只能放弃继承
interface Business { }
// 商业贷业务
class CommercialLoan implements Business { }
// 贷款业务
class PersonalLoan implements Business { }
// 贷款部门
class LoanDepartment {
constructor(businessType) {
if (businessType == 'Commercial') {
return new CommercialLoan()
} else if (businessType == 'Personal') {
return new PersonalLoan()
}
}
}
// 协助岗位
class Salesman {
public static takeMoney(departmentType, businessType) {
if (departmentType === 'Loan') {
return new LoanDepartment(businessType)
}
}
}
let loan = Salesman.takeMoney('Loan', 'Commercial')
几周过后,用户和协助人员都不干了
- 用户去贷款部门办理多个业务,还需要找协助人员两次,客户觉得很麻烦,还不如自己去找
- 协助人员每次去完成业务,先找部门,再找不同的业务,腿都跑断
业务完成耗时,流程复杂,董事长学过设计模式,他宣布以后协助人员只负责给用户指路,让用户自己去完成业务
interface Business { }
// 商业贷业务
class CommercialLoan implements Business { }
// 贷款业务
class PersonalLoan implements Business { }
// 贷款部门
class LoanDepartment {
constructor(businessType) {
if (businessType == 'Commercial') {
return new CommercialLoan()
} else if (businessType == 'Personal') {
return new PersonalLoan()
}
}
}
// 协助岗位
class Salesman {
public static takeMoney(departmentType) {
if (departmentType === 'Loan') {
return LoanDepartment
}
}
}
//贷款部门
let Loan = Salesman.takeMoney('Loan')
// 商业贷业务
let commercial = new Loan('Commercial')
// 贷款业务
let personal = new Loan('Personal')
协助员和用户都很开心了,用户可以同时完成多个业务,协助员也可以当一个安静的美男子!!!
抽象工厂模式的核心是把创建类的权利给用户,工厂只负责给用户提供需要的类
,Salesman类
的工作越来越轻松了,每个类都有自己的功能,这很符合单一职责原则
抽象工厂模式的优点
-
开发者的权利增大,让开发者可以自由完成不同的业务
-
工厂类的功能缩小
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情