TypeScript设计模式之工厂
看看用TypeScript怎样实现常见的设计模式,顺便复习一下。
学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到用哪个模式可以解决,UML忘了可以查,思想记住就好。
这里尽量用原创的,实际中能碰到的例子来说明模式的特点和用处。
简单工厂模式 Simple Factory
特点:把同类型产品对象的创建集中到一起,通过工厂来创建,添加新产品时只需加到工厂里即可,也就是把变化封装起来,同时还可以隐藏产品细节。
用处:要new多个同一类型对象时可以考虑使用简单工厂。
注意:对象需要继承自同一个接口。
下面用TypeScript写一个枪工厂来看看简单工厂模式:
enum GunType{
AK,
M4A1,
}
interface Shootable{
shoot();
}
abstract class Gun implements Shootable{ // 抽象产品 - 枪
abstract shoot();
}
class AK47 extends Gun{ //具体产品 - AK47
shoot(){
console.log('ak47 shoot.');
}
}
class M4A1 extends Gun{ //具体产品 - M4A1
shoot(){
console.log('m4a1 shoot.');
}
}
class GunFactory{
static createGun(type: GunType): Gun{
switch(type){
case GunType.AK:
return new AK47();
case GunType.M4A1:
return new M4A1();
default:
throw Error('not support this gun yet');
}
}
}
GunFactory.createGun(GunType.AK).shoot();
GunFactory.createGun(GunType.M4A1).shoot();
//输出
ak47 shoot.
m4a1 shoot.
上面代码GunFactory
工厂就是根据类型来创建不同的产品,使用的时候只需要引入这个工厂和接口即可。
这样就把变化封装到了工厂中,如果以后要支持狙击枪,只需要加个实现Gun
接口的Sniper
类就可以了。
工厂方法模式 Factory Method
特点:把工厂抽象出来,让子工厂来决定怎么生产产品, 每个产品都由自己的工厂生产。
用处:当产品对象需要进行不同的加工时可以考虑工厂方法。
注意:这不是所谓的简单工厂的升级版,两者有不同的应用场景。
继续用TypeScript写一个枪工厂来看看工厂方法模式:
interface Shootable{
shoot();
}
abstract class Gun implements Shootable{ // 抽象产品 - 枪
abstract shoot();
}
class AK47 extends Gun{ //具体产品 - AK47
shoot(){
console.log('ak47 shoot.');
}
}
class M4A1 extends Gun{ //具体产品 - M4A1
shoot(){
console.log('m4a1 shoot.');
}
}
abstract class GunFactory{ //抽象枪工厂
abstract create(): Gun;
}
class AK47Factory extends GunFactory{ //Ak47工厂
create(): Gun{
let gun = new AK47(); // 生产Ak47
console.log('produce ak47 gun.');
this.clean(gun); // 清理工作
this.applyTungOil(gun);// Ak47是木头枪托,涂上桐油
return gun;
}
private clean(gun: Gun){
//清洗
console.log('clean gun.');
}
private applyTungOil(gun: Gun){
//涂上桐油
console.log('apply tung oil.');
}
}
class M4A1Factory extends GunFactory{ //M4A1工厂
create(): Gun{
let gun = new M4A1(); // 生产M4A1
console.log('produce m4a1 gun.');
this.clean(gun); // 清理工作
this.sprayPaint(gun); // M4是全金属,喷上漆
return gun;
}
private clean(gun: Gun){
//清洗
console.log('clean gun.');
}
private sprayPaint(gun: Gun){
//喷漆
console.log('spray paint.');
}
}
let ak47 = new AK47Factory().create();
ak47.shoot();
let m4a1 = new M4A1Factory().create();
m4a1.shoot();
//output
produce ak47 gun.
clean gun.
apply tung oil.
ak47 shoot.
produce m4a1 gun.
clean gun.
spray paint.
m4a1 shoot.
可以看到Ak47和M4A1在生产出来后的处理不一样,Ak需要涂桐油,M4需要喷漆,用简单工厂就比较难做到,所以就每个产品都弄个工厂来封装各自己的生产过程。
另外的好处是当加入其他枪比如沙漠之鹰时,再加一个产品和产品工厂就好了,并不需要改变现有代码,算是做到了遵守开闭原则。
缺点也明显,增加一个产品就需要多加两个类,增加了代码复杂性。
抽象工厂模式 Abstract Factory
特点:同样隐藏了具体产品的生产,不过生产的是多种类产品。
用处:当需要生产的是一个产品族,并且产品之间或多或少有关联时可以考虑抽象工厂方法。
注意:和工厂方法的区别,工厂方法是一个产品, 而抽象工厂是产品族,线和面的区别。
继续用枪,外加子弹,用TypeScript写一个抽象枪工厂来看看抽象工厂模式:
interface Shootable{
shoot();
}
abstract class Gun implements Shootable{ // 抽象产品 - 枪
private _bullet: Bullet;
addBullet(bullet: Bullet){
this._bullet = bullet;
}
abstract shoot();
}
class AK47 extends Gun{ //具体产品 - AK47
shoot(){
console.log(`ak47 shoot with ${this._bullet}.`);
}
}
class M4A1 extends Gun{ //具体产品 - M4A1
shoot(){
console.log(`m4a1 shoot with ${this._bullet}.`);
}
}
abstract class Bullet{ // 抽象子弹
abstract name: string;
}
class AkBullet{ // AK 子弹
name: string = 'ak bullet';
}
class M4Bullet{ // m4a1 子弹
name: string = 'm4a1 bullet';
}
abstract class ArmFactory{ //抽象军工厂
abstract createGun(): Gun;
abstract createBullet(): Bullet;
}
class AK47Factory extends ArmFactory{
createGun(): Gun{
let gun = new AK47(); // 生产Ak47
console.log('produce ak47 gun.');
this.clean(gun); // 清理工作
this.applyTungOil(gun);// Ak47是木头枪托,涂上桐油
return gun;
}
private clean(gun: Gun){
//清洗
console.log('clean gun.');
}
private applyTungOil(gun: Gun){
//涂上桐油
console.log('apply tung oil.');
}
createBullet(): Bullet{
return new AkBullet();
}
}
class M4A1Factory extends ArmFactory{ //M4A1工厂
createGun(): Gun{
let gun = new M4A1(); // 生产M4A1
console.log('produce m4a1 gun.');
this.clean(gun); // 清理工作
this.sprayPaint(gun); // M4是全金属,喷上漆
return gun;
}
private clean(gun: Gun){
//清洗
console.log('clean gun.');
}
private sprayPaint(gun: Gun){
//喷漆
console.log('spray paint.');
}
createBullet(): Bullet{
return new M4Bullet();
}
}
//使用
function shoot(gun: Gun, bullet: Bullet) // 使用生产的枪和子弹
{
gun.addBullet(bullet);
gun.shoot();
}
let akFactory = new AK47Factory();
shoot(akFactory.createGun(), akFactory.createBullet());
let m4a1Factory = new M4A1Factory();
shoot(m4a1Factory.createGun(), m4a1Factory.createBullet());
//输出
produce ak47 gun.
clean gun.
apply tung oil.
add bullet: ak bullet
ak47 shoot with ak bullet.
produce m4a1 gun.
clean gun.
spray paint.
add bullet: m4a1 bullet
m4a1 shoot with m4a1 bullet.
工厂除了生产枪外还生产子弹,子弹和枪算是一个产品族,使用者接触到的只有抽象工厂和抽象产品,隐藏了具体实现细节。
在大的框架下面有很多小项目时用抽象工厂配合如动态对象生成之类的技术就可以很容易实现灵活的架构。
TypeScript设计模式之工厂的更多相关文章
- 【TS】358- 浅析 TypeScript 设计模式
点击上方"前端自习课"关注,学习起来~ 作者:DD菜 https://zhuanlan.zhihu.com/p/43283016 设计模式就是软件开发过程中形成的套路,就如同你在玩 ...
- C#设计模式(3)——工厂方法模式
一.概念:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 二.代码实现 namespace 设计模式之工厂方法模式 { /// <summary&g ...
- Java设计模式之工厂模式(Factory)
前言: 前面学习了建造者设计模式,接下来学习一下Retrofit中使用的另外一个设计模式,工厂设计模式!!!里面采用工厂模式使得数据转换得到完全解耦,工厂模式的好处用到了极致,如此好的设计模式我们怎能 ...
- 设计模式——抽象工厂模式及java实现
设计模式--抽象工厂模式及java实现 设计模式在大型软件工程中很重要,软件工程中采用了优秀的设计模式有利于代码维护,方便日后更改和添加功能. 设计模式有很多,而且也随着时间在不断增多,其中最著名的是 ...
- java 23 - 1 设计模式之工厂方法模式
转载: JAVA设计模式之工厂模式(简单工厂模式+工厂方法模式)
- 5. 星际争霸之php设计模式--抽象工厂模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- 3. 星际争霸之php设计模式--简单工厂模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- iOS 设计模式之工厂模式
iOS 设计模式之工厂模式 分类: 设计模式2014-02-10 18:05 11020人阅读 评论(2) 收藏 举报 ios设计模式 工厂模式我的理解是:他就是为了创建对象的 创建对象的时候,我们一 ...
- 设计模式之工厂模式(Factory)
设计模式的工厂模式一共有三种:简单工厂模式,工厂模式,抽象工厂模式 简单工厂模式原理:只有一个工厂类,通过传参的形式确定所创建的产品对象种类 代码如下: #include <stdio.h> ...
随机推荐
- HUD-5124-lines
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5124 这题题目做的好悲催,比赛时题目意思不理解,也没有深究了,赛后又看了很久没有看懂,问了很多才搞懂, ...
- 部署JForum 2.1.9遇到的问题及解决方法
1. 主要问题是出在连接数据库和创建表阶段,当我们配置好MySQL的各种参数后,创建表的时候会报错: 原因:主要是由于建表的SQL语句和MySQL的版本不一致导致的. 解决办法:简单来说,在MYSQL ...
- HoloLens开发手记 - 开始使用Vuforia Getting started with Vuforia
Vuforia在6.1版本的Unity SDK里实现了对HoloLens的支持. 查看 Developing for Windows 10 in Unity 这篇文章来了解如何配置Unity和Visu ...
- 源码(07) -- java.util.Iterator<E>
java.util.Iterator<E> 源码分析(JDK1.7) ----------------------------------------------------------- ...
- removeAll
问题:无法移除2个集合中相同元素 方法:移除所包含的其所有元素. 在执行removeAll方法时,会先对集合元素进行比较,如果元素相等才执行移除操作,说到这,相信很多人都已经明白是怎么回事了,因为不相 ...
- Use Prerender to improve AngularJS SEO
Use Prerender to improve AngularJS SEO Nuget Package of ASP.NET MVC HttpModule for prerender.io: Ins ...
- 隐藏Apache的版本号及其它敏感信息
首先,打开配置文件: /etc/apache2/apache2.conf 来修改ServerTokens 的配置: 找到:ServerTokens Full 所在行,将其改为: ServerToken ...
- Linux文件权限及用户管理
/etc/passwd文件与 /etc/shadow文件/etc/passwd文件/etc/passwd文件主要存放登录名.UID等用户相关信息,用户登录密码存放在/etc/shadow文件中.例子: ...
- Java中显示图片的方法
最近在做一个swing小项目,其中需要把存储在硬盘中的图片文件显示出来,总结了如下方法: 1. Graphics g = getGraphics();String name = "E:/Ca ...
- Ubuntu下搭建FTP服务器
Ubuntu下搭建FTP服务器 我装的服务器系统是Ubuntu 12.04 LTS,FTP软件当然是选择大名鼎鼎的vsftpd(very secure FTP daemon), 用系统自带的FTP还好 ...