TypeScript设计模式之策略、模板方法
看看用TypeScript怎样实现常见的设计模式,顺便复习一下。
学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到用哪个模式可以解决,UML忘了可以查,思想记住就好。
这里尽量用原创的,实际中能碰到的例子来说明模式的特点和用处。
策略模式 Strategy
特点:用组合的方式调用一些算法或逻辑,并且可以根据状态不同而选用不同的算法或逻辑。
用处:对象需要运行时切换算法或逻辑可以考虑使用策略模式。
注意:策略的生成方式。
下面用TypeScript简单实现一个策略模式:
说起策略就想到策略类游戏,年龄大点的可能都玩过War3,人族对兽族时如果侦察到对方不着急升本,用常规万金油打法,那人族就可以出狗男女来一波流。
如果侦察到兽族跳科技并摆下两个兽栏,那对方可能是暴飞龙,人族就要家里补个塔防偷农民,然后出点火枪或二本龙鹰。
class Orc{
private _shenKeJi = false;
get shenKeJi(): boolean { // 这里简单用升科技来判断是用常规还是飞龙
return this._shenKeJi;
}
set shenKeJi(value: boolean){
this._shenKeJi = value;
}
}
abstract class Stragety{
abstract execute();
}
class RushStragety extends Stragety{
execute(){
console.log('升科技');
console.log('出狗男女');
console.log('一波流');
}
}
class DefendStragety extends Stragety{
execute(){
console.log('补塔防飞龙');
console.log('出火枪');
console.log('升科技');
console.log('出龙鹰');
}
}
class Human{
stragety: Stragety;
checkOrc(orc: Orc){
if(orc.shenKeJi){ //根据兽族情况来决定策略
console.log('侦察到兽族是跳科技打法');
this.stragety = new DefendStragety();
} else {
console.log('侦察到兽族是常规打法');
this.stragety = new RushStragety();
}
}
deal(){
this.stragety && this.stragety.execute();
}
}
let orc = new Orc();
let human = new Human();
orc.shenKeJi = false;
human.checkOrc(orc);
human.deal();
orc.shenKeJi = true;
human.checkOrc(orc);
human.deal();
//输出
侦察到兽族是常规打法
升科技
出狗男女
一波流
侦察到兽族是跳科技打法
补塔防飞龙
出火枪
升科技
出龙鹰
这样人族就可以根据兽族的状态改变来做出不同的应对策略,其实现在游戏的AI基本都是通过决策树来实现的,也算是策略模式,只是更复杂,通过各种不同的条件最终得到一个决策来做出反应。
另外,有人可能已经发现了,上面生成策略的地方是可以拿出来,用之前讲的工厂模式来做,因为实际应用时策略通常比较多,甚至可能同时需要多种相关策略,用工厂模式来生产策略就可以很好的隐藏细节,解除依赖。
模板方法模式 Template Method
特点:通过多态来实现在运行时使用不同的算法或逻辑,通常有一个整体架子,通过抽象方法或虚方法来把细节代码延迟到子类实现。
用处:当多个类似功能的类有很多相同结构或代码时,可以抽象出整体架子时可以考虑模板方法。
注意:与策略模式的异同:同样是细节部分交出去,不同在于策略是对象行为,采用的是组合的方式,而模板方法是类行为,采用的是继承。
下面用TypeScript简单实现一个模板方法模式:
比方说发送http请求的代码,需要向两台不同的server(A和B)发送请求,两台server除了url不同,回来的数据格式也不一样,但由于都是http请求,主体架子是一样的,所以可以用模板方法来实现下。
class ClassA{} // Server A 返回的数据结构
class ClassB{} // Server B 返回的数据结构
abstract class RequesterBase<T>{
constructor(private url: string){
}
reqeustData(): T{
this.sendReqeust();
return this.handleResponse();
}
protected sendReqeust(){
console.log(`send request, url: ${this.url}`);
}
protected abstract handleResponse(): T; // 不同的server返回的数据交由子类去实现
}
class RequesterForServerA extends RequesterBase<ClassA>{
protected handleResponse(): ClassA{
console.log('handle response for Server A');
return null;
}
}
class RequesterForServerB extends RequesterBase<ClassB>{
protected handleResponse(): ClassB{
console.log('handle response for Server B');
return null;
}
}
let requesterA: RequesterBase<ClassA> = new RequesterForServerA('server A');
let requesterB: RequesterBase<ClassB> = new RequesterForServerB('server B');
requesterA.reqeustData();
requesterB.reqeustData();
//输出
send request, url: server A
handle response for Server A
send request, url: server B
handle response for Server B
这里可以看到主体功能由基类RequesterBase实现,两个子类则实现解析数据这些细节,这样就达到了消除重复代码的目的。
如果还有个ServerC的request发送部分也不一样,也没关系,TypeScript天生虚函数,在子类直接实现reqeustData即可,多态的作用下,运行时还是会调用到子类上。
TypeScript设计模式之策略、模板方法的更多相关文章
- SpringMvc接口中转设计(策略+模板方法)
一.前言 最近带着两个兄弟做支付宝小程序后端相关的开发,小程序首页涉及到很多查询的服务.小程序后端服务在我司属于互联网域,相关的查询服务已经在核心域存在了,查询这块所要做的工作就是做接口中转.参考了微 ...
- 【设计模式】【应用】使用模板方法设计模式、策略模式 处理DAO中的增删改查
原文:使用模板方法设计模式.策略模式 处理DAO中的增删改查 关于模板模式和策略模式参考前面的文章. 分析 在dao中,我们经常要做增删改查操作,如果每个对每个业务对象的操作都写一遍,代码量非常庞大. ...
- 设计模式 ( 十九 ) 模板方法模式Template method(类行为型)
设计模式 ( 十九 ) 模板方法模式Template method(类行为型) 1.概述 在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行 ...
- 设计模式:策略模式(Strategy)
定 义:它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化, 不会影响到使用算法的客户. 示例:商场收银系统,实现正常收费.满300返100.打8折.......等不同收费 ...
- PHP设计模式之策略模式
前提: 在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查 找.排序等,一种常用的方法是硬编码(Hard Cod ...
- JavaScript设计模式之策略模式(学习笔记)
在网上搜索“为什么MVC不是一种设计模式呢?”其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选 ...
- 乐在其中设计模式(C#) - 策略模式(Strategy Pattern)
原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabc ...
- 【java设计模式】之 模板方法(Template Method)模式
1. 模板方法的一个实例 这一节主要来学习一下设计模式中的模板方法模式.我们先来看一个例子:假如现在老板让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验 ...
- JavaScript设计模式之策略模式
所谓"条条道路通罗马",在现实中,为达到某种目的往往不是只有一种方法.比如挣钱养家:可以做点小生意,可以打分工,甚至还可以是偷.抢.赌等等各种手段.在程序语言设计中,也会遇到这种类 ...
随机推荐
- iOS 之 assign、retain、copy、nonatomic
1. assign 1.1. 普通赋值 一般用于基本类型 1.2. 常见委托设计模式 防止循环引用 2. retain 保留计数,获取了对象的所有权.引用计数在原有基础上加1. 3. copy 同re ...
- CentOS 6.6下JDK1.7安装与配置(Linux)经典入门详解案例
最近用的linux较多,在网站找了一些关于linux环境下jdk安装的教程,过程是有的但是好多细节都没有表现出来,所以我花了点时间总结了一下,希望对大家都有帮助... CentOS下JDK1.7安装与 ...
- delphi假死线程堵塞解决办法
Delphi的高效不多说... 俗话说:真正的程序员用C语言,聪明的程序员用Delphi,一点都不假,和C++比它比C++更简单,更容易上手,功能丝毫不逊色C++,比起VB,毫无疑问比VB好多了,重要 ...
- MyBatis 延迟加载
在sqlMapConfig中进行设置 <configuration> <settings> <!--延迟加载的总开关--> <setting name=&qu ...
- 你真的懂ajax吗?
前言 总括: 本文讲解了ajax的历史,工作原理以及优缺点,对XMLHttpRequest对象进行了详细的讲解,并使用原生js实现了一个ajax对象以方便日常开始使用. damonare的ajax库: ...
- 一个web应用的诞生--美化一下
经过上一章的内容,其实就页面层来说已结可以很轻松的实现功能了,但是很明显美观上还有很大的欠缺,现在有一些很好的前端css框架,如AmazeUI,腾讯的WeUI等等,这里推荐一个和flask集成很好的b ...
- 访问量分类统计(QQ,微信,微博,网页,网站APP,其他)
刚准备敲键盘,突然想起今天已经星期五了,有点小兴奋,一周又这么愉快的结束,又可以休息了,等等..我好像是来写Java博客的,怎么变成了写日记,好吧,言归正传. 不知道大家有没有遇到过这样的需求:统计一 ...
- Linux文件权限及用户管理
/etc/passwd文件与 /etc/shadow文件/etc/passwd文件/etc/passwd文件主要存放登录名.UID等用户相关信息,用户登录密码存放在/etc/shadow文件中.例子: ...
- Linux驱动技术(七) _内核定时器与延迟工作
内核定时器 软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行.实际上,时钟中断处理程 ...
- android jni 总复习(转载)
本文全文转载自:http://www.cnblogs.com/shuqingstudy/p/4909089.html,非常感谢 package com.test.androidjni; import ...