看看用TypeScript怎样实现常见的设计模式,顺便复习一下。

学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到用哪个模式可以解决,UML忘了可以查,思想记住就好。

这里尽量用原创的,实际中能碰到的例子来说明模式的特点和用处。

单例模式 Singleton

特点:在程序的生命周期内只有一个全局的实例,并且不能再new出新的实例。

用处:在一些只需要一个对象存在的情况下,可以使用单例,比如Cache, ThreadPool等。

注意:线程安全,当然,这在单线程的JavaScript环境里是不存在的。

下面用TypeScript写一个Cache来看看单例模式:

class Cache{
public static readonly Instance: Cache = new Cache(); private _items: {[key: string]: string} = {}; private Cache(){ } set(key: string, value: string){
this._items[key] = value;
console.log(`set cache with key: '${key}', value: '${value}'`);
} get(key: string): string{
let value = this._items[key];
console.log(`get cache value: '${value}' with key: '${key}'`);
return value;
}
} Cache.Instance.set('name', 'brook');
Cache.Instance.get('name');

输出:

set cache with key: 'name', value: 'brook'
get cache value: 'brook' with key: 'name'

很简单, 和C#基本一样, 设置一个全局只读的Instance并且把构造函数设为private,这样就确保了单例的特点。

可能有人有疑问:静态Instance在C#里能确保只有一个是CLR的功劳,这里每次访问Instance会不会重新new一个呢?

带着疑问来看看上面代码编译成JavaScript ES6的结果:

class Cache {
constructor() {
this._items = {};
}
Cache() {
}
set(key, value) {
this._items[key] = value;
console.log(`set cache with key: '${key}', value: '${value}'`);
}
get(key) {
let value = this._items[key];
console.log(`get cache value: '${value}' with key: '${key}'`);
return value;
}
}
Cache.Instance = new Cache();
Cache.Instance.set('name', 'brook');
Cache.Instance.get('name');

可以看到TypeScript的静态实例Instance其实是直接加到了Cache本身上面,当然也就确保了不会再new出新的来。

建造者模式 Builder

特点:一步一步来构建一个复杂对象,可以用不同组合或顺序建造出不同意义的对象,通常使用者并不需要知道建造的细节,通常使用链式调用来构建对象。

用处:当对象像积木一样灵活,并且需要使用者来自己组装时可以采用此模式,好处是不需要知道细节,调用方法即可,常用来构建如Http请求、生成器等。

注意:和工厂模式的区别,工厂是生产产品,谁生产,怎样生产无所谓,而建造者重在组装产品,层级不一样。

下面用TypeScript写一个Http的RequestBuilder来看看建造者模式:

enum HttpMethod{
GET,
POST,
} class HttpRequest {} //假设这是最终要发送的request class RequestBuilder{ private _method: HttpMethod; private _headers: {[key: string]: string} = {}; private _querys: {[key: string]: string} = {}; private _body: string; setMethod(method: HttpMethod): RequestBuilder{
this._method = method;
return this;
} setHeader(key: string, value: string): RequestBuilder{
this._headers[key] = value;
return this;
} setQuery(key: string, value: string): RequestBuilder{
this._querys[key] = value;
return this;
} setBody(body: string): RequestBuilder{
this._body = body;
return this;
} build(): HttpRequest {
// 根据上面信息生成HttpRequest
}
} let getRequest = new RequestBuilder()
.setMethod(HttpMethod.GET)
.setQuery('name', 'brook')
.build(); let postRequest = new RequestBuilder()
.setMethod(HttpMethod.POST)
.setHeader('ContentType', 'application/json')
.setBody('body')
.build();

上面RequestBuilder可以根据传进来的参数不同来构建出不同的HttpReqeust对象,这样使用者就可以按照自己需求来生成想要的对象。

这里有个问题是RequestBuilder需不需要抽象出来,个人觉得要看情况而定。

首先是保持简单,不去套UML,只是一个简单的构造功能给内部使用也没必要抽象来增加代码复杂度,但如果业务上这个Builder是封装在一个库里面并且要对外提供服务,那还是需要一个抽象来隐藏细节,消除对实现的依赖。

并且如果业务上还需要不同的RequestBuilder,比如说XmlRequestBuilder JsonRequestBuilder之类,那就更需要一个抽象了。

原型模式 Prototype

特点:不需要知道对象构建的细节,直接从对象上克隆出来。

用处:当对象的构建比较复杂时或者想得到目标对象相同内容的对象时可以考虑原型模式。

注意:深拷贝和浅拷贝。

JavaScript对这个应该是太了解了,天生就有Prototype,通过Object.create就可以根据对象原型创建一个新的对象。

class Origin{
name: string
} let origin = new Origin();
origin.name = 'brook'; let cloneObj = Object.create(origin);
console.log(cloneObj.name); // brook

不过还是用代码简单实现一下原型模式

interface Clonable<T>{
clone(): T;
} class Origin implements Clonable<Origin>{
name: string; clone(): Origin{
let target = new Origin();
target.name = this.name;
return target;
}
} let origin = new Origin();
origin.name = 'brook'; let cloneObj = origin.clone();
console.log(cloneObj.name); // brook

实现Clonable接口的都具有Clone功能,通过Clone功能就可以实现对象的快速复制,如果属性很多,想另外创建属性值也差不多相同的对象,原型就可以派上用场。

当然,还是要注意深拷贝和浅拷贝的问题,上面的代码只有string,所以浅拷贝没有问题,如果有对象就需要注意浅拷贝是否能满足要求。

TypeScript设计模式之单例、建造者、原型的更多相关文章

  1. java软件设计模式只单例设计模式

    概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计 ...

  2. Spring5源码解析-Spring框架中的单例和原型bean

    Spring5源码解析-Spring框架中的单例和原型bean 最近一直有问我单例和原型bean的一些原理性问题,这里就开一篇来说说的 通过Spring中的依赖注入极大方便了我们的开发.在xml通过& ...

  3. iOS 设计模式之单例

    设计模式:单例 一.  单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例类的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并 ...

  4. 设计模式——懒汉式单例类PK饿汉式单例类

    前言 我们都知道生活中好多小软件,有的支持多IP在线,有的仅仅局限于单个IP在线.为什么这样设计,在软件开发阶段就是,有需求就是发展.这就是软件开发的一个设计模式--懒汉式单例类和饿汉式单例类. 内容 ...

  5. 详略。。设计模式1——单例。。。。studying

    设计模式1--单例 解决:保证了一个类在内存中仅仅能有一个对象. 怎么做才干保证这个对象是唯一的呢? 思路: 1.假设其它程序可以任意用new创建该类对象,那么就无法控制个数.因此,不让其它程序用ne ...

  6. 游戏设计模式——C++单例类

    前言: 本文将探讨单例类设计模式,单例类的懒汉模式/饿汉模式,单例类的多线程安全性,最后将利用C++模板减少单例类代码量. 本文假设有一个Manager管理类,并以此为探究单例类的设计模式. 懒汉模式 ...

  7. 两种设计模式(2)==>>"单例"

    所谓“单例”: 单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资 ...

  8. OC中的单例设计模式及单例的宏抽取

    // 在一个对象需要重复使用,并且很频繁时,可以对对象使用单例设计模式 // 单例的设计其实就是多alloc内部的allocWithZone下手,重写该方法 #pragma Person.h文件 #i ...

  9. [译]Java 设计模式之单例

    (文章翻译自Java Design Pattern: Singleton) 单例是在Java最经常被用到的设计模式.它通过阻止其他的实例化和修改来用于控制创建对象的数目.这一特性可应用于那些当只有一个 ...

随机推荐

  1. 得到css style

    //根据ID返回dom元素 2 var $ = function(id){return document.getElementById(id);} 3 //返回dom元素的当前某css值 4 var ...

  2. TortoiseSVN使用简介(收藏)

    TortoiseSVN使用简介 1.安装及下载client 端 2.什么是SVN(Subversion)? 3.为甚么要用SVN? 4.怎么样在Windows下面建立SVN Repository? 5 ...

  3. 封装bt轮播图淡入淡出效果样式

    <!--BT轮播图-->    <div data-ride="carousel" class="carousel slide carousel_inn ...

  4. Oracle 11g RAC使用Manual和Policy Managed方法配置(转)

    原文地址:http://czmmiao.iteye.com/blog/2128771 软件环境: 操作系统:Red Hat Enterprise Linux 5.4(Tikanga)Oracle:11 ...

  5. 【HDU 5808】 Price List Strike Back (整体二分+动态规划)

    Price List Strike Back There are nn shops numbered with successive integers from 11 to nn in Bytelan ...

  6. 使用Flex构建Web和移动参考应用程序

    范例文件 Shopping Cart Sales Dashboard Expense Tracker 需要的其他产品 Android 2.2及更高版本或Android 3.0及更高版本的设备 仅仅在F ...

  7. jQuery disabled 元素

    http://www.jb51.net/article/19342.htm 在jquery中可以通过jqueryObj.attr("disabled","disabled ...

  8. 3D游戏开发之在UE4中创建非玩家角色(NPC)

    接着上节我们继续学习,现在我们来创建一些NPC(non-playable characters,非玩家角色).在这个游戏中,当我们靠近NPC时,它们会做出相应的反应. 一 创建C++类 1) 在UE编 ...

  9. 华为oj---合并数组

    题目标题: 将两个整型数组按照升序合并,并且过滤掉重复数组元素 详细描述: 接口说明 原型: voidCombineBySort(int* pArray1,intiArray1Num,int* pAr ...

  10. html 一般标签 常用标签 表格

    body的属性: bgcolor                页面背景色 background            背景壁纸.图片 text                    文字颜色 top ...