设计模式分类
创建型模式
提供了一种在创建对象的同时隐藏创建逻辑的方式
而不是直接使用new
运算符来直接实例化对象
- 工厂方法模式
- 抽象工厂模式
- 单例模式
- 建造者模式
- 原型模式
结构型模式
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 桥接模式
- 组合模式
- 享元模式
行为型模式
- 策略模式
- 模板方法
- 观察者
- 迭代子模式
- 责任链模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式
工厂模式
- 工厂模式是用来创建对象的一种最常用的设计模式(创建型)。我们不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂
- 工厂模式根据抽象程度的不同可以分为:简单工厂,工厂方法和抽象工厂
简单工厂
- 简单工厂模式又称静态工厂方法模式。可以根据不同的参数返回不同类的实例
- 简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的类通常具有共同的父类
- 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品
- 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。
- 具体产品角色:工厂类所创建的对象就是此角色的实例。
/**
* 生产电视机的工厂
* haier Hisense
* */
// 抽象产品类 (接口)
interface TV {
play(): void;
}
// 具体产品
class HaierTV implements TV {
play(): void {
console.log('海尔电视机播放')
}
}
class HisenseTV implements TV {
play(): void {
console.log('海信电视机播放')
}
}
// 工厂类
class TVFactory {
static createTV(type: string): any {
switch(type) {
case "Haier":
return new HaierTV();
case "Hisense":
return new HisenseTV();
default:
break;
}
return new HaierTV;
}
}
let haier = TVFactory.createTV("Haier");
haier.play();
let hisense = TVFactory.createTV("Hisense");
hisense.play();
--------------------
tsc index.ts
node index.js
海尔电视机播放
海信电视机播放
优缺点
优点
- 使用者无需知道所创建的具体产品类的类名,只需要知道具体产品所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量
- 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点
- 工厂类的逻辑一旦不能正常的工作,整个系统都要受到影响
- 简单工厂模式增加系统中类的个数,在一定程度上增加了系统的复杂度
- 如果添加了产品,就不得不修改工厂逻辑
- 工厂类(静态方法)无法被继承
工厂方法
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担
一个抽象工厂类,新增具体工厂分别实现
// 抽象工厂类
interface TVFactory {
createTV(): any;
}
// 具体工厂
class HaierTVFactory implements TVFactory{
createTV() : HaierTV {
return new HaierTV();
}
}
class HisenseTVFactory implements TVFactory{
createTV() : HisenseTV {
return new HisenseTV();
}
}
let haier = new HaierTVFactory();
haier.createTV().play();
let hisense = new HisenseTVFactory();
hisense.createTV().play();
以后需要添加产品和功能只需添加具体的产品和具体的工厂
增加一个具体产品
class TclTV implements TV{
play(): void {
console.log('Tcl电视机播放')
}
}
增加一个具体工厂并实例化
class TclTVFactor implements TVFactory{
createTV() : TclTV {
return new TclTV();
}
}
let tcl = new TclTVFactor();
tcl.createTV().play();
优缺点
简单工厂模式只有一个工厂,工厂方法模式对每一个产品都有相应的工厂,
当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。
好处
- 增加一个产品类,只需要增加产品类和相对应的工厂,两个类,不需要修改工厂类。(开闭原则)
- 使用者只需要关心所需要产品的工厂,无需要创建的一些细节
缺点:
- 添加新产品时,需要编写新的具体产品类,还需要提供对应的具体工厂类,系统类成倍增加,在一定的程度上增加了系统的复杂度,也给系统带来了额外的开销。
抽象工厂
工厂方法模式中一个具体工厂只能生产一种产品,而抽象工厂模式一个具体工厂可以生产多个产品
比如说手机零件工厂,会生产并供应给多个品牌的
// 抽象类 (接口)
interface AbsLocation {
startLocateWithResult(): void;
}
interface AbsMapView {
initWithFrame(): void;
}
// 具体产品
class AbsBaiduLocation implements AbsLocation {
startLocateWithResult(): void {
console.log('百度位置')
}
}
class AbsBaiduMapView implements AbsMapView {
initWithFrame(): void {
console.log('百度地图显示')
}
}
class AbsGaodeLocation implements AbsLocation {
startLocateWithResult(): void {
console.log('高德位置')
}
}
class AbsGaodeMapView implements AbsMapView {
initWithFrame(): void {
console.log('高德地图显示')
}
}
// 抽象工厂
interface AbsFactory {
creatMap(): any;
createLocation(): any;
}
// 具体工厂 既可以生产高德产品,也可以生产百度地图产品
class AbsGaodeMapFactory implements AbsFactory {
createLocation(): AbsGaodeLocation {
return new AbsGaodeLocation();
}
creatMap(): AbsGaodeMapView {
return new AbsGaodeMapView();
}
}
class AbsBaiduMapFactory implements AbsFactory {
createLocation(): AbsBaiduLocation {
return new AbsBaiduLocation();
}
creatMap(): AbsBaiduMapView {
return new AbsBaiduMapView();
}
}
let baidu = new AbsBaiduMapFactory();
baidu.creatMap().initWithFrame();
baidu.createLocation().startLocateWithResult();
数据库连接实例
interface DBConnection {
connection(): void;
}
interface DBOperate {
select(): void;
delete(): void;
update(): void;
insert(): void;
}
interface DBFactory {
create(): void;
operate(): void;
}
class MySQLConn implements DBConnection {
connection(): void {
console.log("连接上了MySQL");
}
}
class SQLServerConn implements DBConnection {
connection(): void {
console.log("连接上了SQLServer");
}
}
class MySQLOperate implements DBOperate {
select(): void {
console.log("MySQL--select")
}
delete(): void {
console.log("MySQL--delete")
}
update(): void {
console.log("MySQL--update")
}
insert(): void {
console.log("MySQL--insert")
}
}
class SQLServerOperate implements DBOperate {
select(): void {
console.log("SQLServer--select")
}
delete(): void {
console.log("SQLServer--delete")
}
update(): void {
console.log("SQLServer--update")
}
insert(): void {
console.log("SQLServer--insert")
}
}
class MySQLFactory implements DBFactory {
create(): MySQLConn {
return new MySQLConn();
}
operate(): MySQLOperate {
return new MySQLOperate();
}
}
class SQLServerFactory implements DBFactory {
create(): SQLServerConn {
return new SQLServerConn();
}
operate(): SQLServerOperate {
return new SQLServerOperate();
}
}
const mysql = new MySQLFactory();
const mysql_create = mysql.create().connection();
const mysql_select = mysql.operate().select();
const mysql_update = mysql.operate().update();
const mysql_delete = mysql.operate().delete();
const mysql_insert = mysql.operate().insert();
const sqlserver = new SQLServerFactory();
const sqlserver_create = sqlserver.create().connection();
const sqlserver_select = sqlserver.operate().select();
const sqlserver_update = sqlserver.operate().update();
const sqlserver_delete = sqlserver.operate().delete();
const sqlserver_insert = sqlserver.operate().insert();