最近学习设计模式和TypeScript
,发现网上的资料略显硬核,不太容易理解记忆,常常看完就忘。做为一名游戏玩家,发现游戏中的不少场景都能和相应的设计模式相关联,不只便于理解,更利于合理地运用设计模式。因为我的水平有限,只整理我的以为比较有趣的设计模式,每一个模式采用哲学三问进行讲解。若是对你有帮助的话,欢迎点赞和收藏💖,图片源自网络,侵删。node
What
定义:一个类仅有一个实例,并提供一个访问它的全局访问点git
解释:实质上就是起到一个存储全局变量的做用,其余的类和模块只能经过该类提供的接口修改其惟一实例github
Game:在DNF
一块儿组团刷本的日子中,副本BOSS
看做为一个单例,玩家能够经过各类技能或者平A去消耗BOSS
。算法
而且该本中的全部玩家都是对同一个BOSS
形成伤害设计模式
How
BOSS
为单例,只会被实例化一次BOSS
形成伤害BOSS
受到的伤害为玩家们形成伤害的总和TS版本网络
class Boss{
private static instance: Boss = null;
private hp: number = 1000;
getInjured(harm: number){
this.hp -= harm;
}
getHp(): number{
return this.hp;
}
static getInstance(): Boss{
// 若是已经实例化了那么直接返回
if(!this.instance){
this.instance = new Boss();
}
return this.instance;
}
}
class Player{
constructor(private name: string){}
attack(harm: number,boss: Boss): void{
boss.getInjured(harm);
console.log(`我是一名${this.name},打出了${harm}伤害,BOSS还剩${boss.getHp()}血`)
}
}
let p1: Player = new Player('鬼泣');
let p2: Player = new Player('街霸');
let p3: Player = new Player('阿修罗');
// 对同一个boss疯狂输出
p1.attack(100,Boss.getInstance());
p2.attack(80,Boss.getInstance());
p3.attack(120,Boss.getInstance());
// 我是一名鬼泣,打出了100伤害,BOSS还剩900血
// 我是一名街霸,打出了80伤害,BOSS还剩820血
// 我是一名阿修罗,打出了120伤害,BOSS还剩700血
复制代码
JS版本dom
var Boss = /** @class */ (function () {
function Boss() {
this.hp = 1000;
}
Boss.prototype.getInjured = function (harm) {
this.hp -= harm;
};
Boss.prototype.getHp = function () {
return this.hp;
};
Boss.getInstance = function () {
// 若是已经实例化了那么直接返回
if (!this.instance) {
this.instance = new Boss();
}
return this.instance;
};
Boss.instance = null;
return Boss;
}());
var Player = /** @class */ (function () {
function Player(name) {
this.name = name;
}
Player.prototype.attack = function (harm, boss) {
boss.getInjured(harm);
console.log("我是一名" + this.name + ",打出了" + harm + "伤害,BOSS还剩" + boss.getHp() + "血");
};
return Player;
}());
var p1 = new Player('鬼泣');
var p2 = new Player('街霸');
var p3 = new Player('阿修罗');
// 对同一个boss疯狂输出
p1.attack(100, Boss.getInstance());
p2.attack(80, Boss.getInstance());
p3.attack(120, Boss.getInstance());
// 我是一名鬼泣,打出了100伤害,BOSS还剩900血
// 我是一名街霸,打出了80伤害,BOSS还剩820血
// 我是一名阿修罗,打出了120伤害,BOSS还剩700血
复制代码
Why
GC
自动回收What
定义:策略模式指的是定义一系列的算法,把它们一个个封装起来。将不变的部分和变化的部分隔开是每一个设计模式的主题,策性能
略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。单元测试
解释:常言道条条大路通罗马
,所谓策略模式也就是为实现某种功能而采起不一样的策略算法学习
Game:在炉石传说游戏中,盗贼的两套经典卡牌奇迹贼和爆牌贼,虽然都是盗贼玩家取胜的法宝,但这两套牌的取胜之道却大相径庭。奇迹贼依靠一回合的极限操做每每能转危为安,让对面忽然去世;而爆牌贼则是以疲劳和爆对面key
牌的运营方式取胜。
How
TS版本
interface Deck{
name: string;
kill(): void;
}
class MiracleDeck implements Deck{
name: string = '奇迹贼';
kill(){
console.log(`${this.name}:十七张牌就是能秒你`);
}
}
class ExplosiveDeck implements Deck{
name: string = '爆牌贼';
kill(){
console.log(`${this.name}:我要爆光你的牌库!`)
}
}
class Robber{
private deck: Deck;
setDeck(deck: Deck){
this.deck = deck;
}
winTheGame(): void{
this.deck.kill();
};
}
let rb = new Robber();
rb.setDeck(new MiracleDeck());
rb.winTheGame();
rb.setDeck(new ExplosiveDeck());
rb.winTheGame();
// 奇迹贼:十七张牌就是能秒你
// 爆牌贼:我要爆光你的牌库!
复制代码
JS版本
var MiracleDeck = /** @class */ (function () {
function MiracleDeck() {
this.name = '奇迹贼';
}
MiracleDeck.prototype.kill = function () {
console.log(this.name + "十七张牌就是能秒你");
};
return MiracleDeck;
}());
var ExplosiveDeck = /** @class */ (function () {
function ExplosiveDeck() {
this.name = '爆牌贼';
}
ExplosiveDeck.prototype.kill = function () {
console.log(this.name + "我要爆光你的牌库!");
};
return ExplosiveDeck;
}());
var Robber = /** @class */ (function () {
function Robber() {
}
Robber.prototype.setDeck = function (deck) {
this.deck = deck;
};
Robber.prototype.winTheGame = function () {
this.deck.kill();
};
;
return Robber;
}());
var rb = new Robber();
rb.setDeck(new MiracleDeck());
rb.winTheGame();
rb.setDeck(new ExplosiveDeck());
rb.winTheGame();
// 奇迹贼:十七张牌就是能秒你
// 爆牌贼:我要爆光你的牌库!
复制代码
Why
What
定义:为一个对象提供一个代理者,以便控制对它的访问
解释:好比明星和经纪人的关系,经纪人会帮助明星处理商演赞助等细节问题,明星负责签字就好
Game:做为一个FM
懒人玩家,只想把时间花在看模拟比赛上,其余不想作的事就很开心地甩给助理教练啦
How
TS版本
interface Match{
play(): void;
}
class Manager implements Match{
play(): void{
console.log('比赛开始了,是由皇家马德里对阵拜仁慕尼黑。。。')
}
}
class Cotch implements Match{
private manager: Manager = new Manager();
beforePlay(): void{
console.log('布置战术');
console.log('球队训话');
}
afterPlay(): void{
console.log('赛后采访');
}
play(): void{
this.beforePlay();
this.manager.play();
this.afterPlay();
}
}
let proxy: Cotch = new Cotch();
proxy.play();
// 布置战术
// 球队训话
// 比赛开始了,是由皇家马德里对阵拜仁慕尼黑。。。
// 赛后采访
复制代码
JS版本
var Manager = /** @class */ (function () {
function Manager() {
}
Manager.prototype.play = function () {
console.log('比赛开始了,是由皇家马德里对阵拜仁慕尼黑。。。');
};
return Manager;
}());
var Cotch = /** @class */ (function () {
function Cotch() {
this.manager = new Manager();
}
Cotch.prototype.beforePlay = function () {
console.log('布置战术');
console.log('球队训话');
};
Cotch.prototype.afterPlay = function () {
console.log('赛后采访');
};
Cotch.prototype.play = function () {
this.beforePlay();
this.manager.play();
this.afterPlay();
};
return Cotch;
}());
var proxy = new Cotch();
proxy.play();
// 布置战术
// 球队训话
// 比赛开始了,是由皇家马德里对阵拜仁慕尼黑。。。
// 赛后采访
复制代码
Why
ES6
中的Proxy
What
定义:对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,全部依赖于它的对象都将获得通知
解释:好比JS
中的addEventListener
Game:进游戏后你会订阅队友和敌人的生存状态,当生存状态发生变化时,系统会及时通知你
How
TS版本
class EventEmitter{
private events: Object = {}; // 存储事件
private key: number = 0; // 事件的惟一标识key
on(name: string,event: any): number{
event.key = ++this.key;
this.events[name] ? this.events[name].push(event)
: (this.events[name] = []) && this.events[name].push(event);
return this.key;
}
off(name: string,key: number){
if(this.events[name]){
this.events[name] = this.events[name].filter(x => x.key !== key);
}else{
this.events[name] = [];
}
}
emit(name: string,key?: number){
if(this.events[name].length === 0 ) throw Error(`抱歉,你没有定义 ${name}监听器`)
if(key){
this.events[name].forEach(x => x.key === key && x());
}else {
this.events[name].forEach(x => x());
}
}
}
let player: EventEmitter = new EventEmitter();
player.on('friendDied',function(): void{
console.log('你可爱的队友已被击杀');
})
player.on('enemyDied',function(): void{
console.log('打的好呀,小帅哥')
})
// 模拟战况
let rand: number;
let k: number = 1;
while(k < 10){
rand = Math.floor(Math.random() * 10);
if(rand % 2 === 0){
player.emit('friendDied');
}else{
player.emit('enemyDied');
}
k++;
}
// 你可爱的队友已被击杀
// 打的好呀,小帅哥
// 你可爱的队友已被击杀
// 你可爱的队友已被击杀
// 打的好呀,小帅哥
// 你可爱的队友已被击杀
// 你可爱的队友已被击杀
// 打的好呀,小帅哥
// 打的好呀,小帅哥
复制代码
JS版本
var EventEmitter = /** @class */ (function () {
function EventEmitter() {
this.events = {}; // 存储事件
this.key = 0; // 事件的惟一标识key
}
EventEmitter.prototype.on = function (name, event) {
event.key = ++this.key;
this.events[name] ? this.events[name].push(event)
: (this.events[name] = []) && this.events[name].push(event);
return this.key;
};
EventEmitter.prototype.off = function (name, key) {
if (this.events[name]) {
this.events[name] = this.events[name].filter(function (x) { return x.key !== key; });
}
else {
this.events[name] = [];
}
};
EventEmitter.prototype.emit = function (name, key) {
if (this.events[name].length === 0)
throw Error("\u62B1\u6B49\uFF0C\u4F60\u6CA1\u6709\u5B9A\u4E49 " + name + "\u76D1\u542C\u5668");
if (key) {
this.events[name].forEach(function (x) { return x.key === key && x(); });
}
else {
this.events[name].forEach(function (x) { return x(); });
}
};
return EventEmitter;
}());
var player = new EventEmitter();
player.on('friendDied', function () {
console.log('你可爱的队友已被击杀');
});
player.on('enemyDied', function () {
console.log('打的好呀,小帅哥');
});
// 模拟战况
var rand;
var k = 1;
while (k < 10) {
rand = Math.floor(Math.random() * 10);
if (rand % 2 === 0) {
player.emit('friendDied');
}
else {
player.emit('enemyDied');
}
k++;
}
// 你可爱的队友已被击杀
// 打的好呀,小帅哥
// 你可爱的队友已被击杀
// 你可爱的队友已被击杀
// 打的好呀,小帅哥
// 你可爱的队友已被击杀
// 你可爱的队友已被击杀
// 打的好呀,小帅哥
// 打的好呀,小帅哥
复制代码
Why
JS
中的addEventListener
和Redux
中的数据流模型What
定义:一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且能够独立地改变它们之间的交互。
解释:简单来讲就是模块之间通讯的中间商
Game:FIFA Online中,你能够在交易系统上上架球员卡,而后该商品会被交易系统转发给其余玩家
How
TS版本
abstract class Shop {
//存储
public fifaers: Object = {}
//注册
public register(name: string, fifaer: Fifaer): void {
if (this.fifaers[name]) {
console.error(`${name}名称已存在`);
} else {
this.fifaers[name] = fifaer;
fifaer.setMedium(this);
}
}
//转发
public relay(fifaer: Fifaer, message?: any): void {
Object.keys(this.fifaers).forEach((name: string) => {
if (this.fifaers[name] !== fifaer) {
this.fifaers[name].receive(message);
}
})
}
}
//抽象玩家类
abstract class Fifaer {
protected mediator: Shop;
public setMedium(mediator: Shop): void {
this.mediator = mediator;
}
public receive(message?: any): void {
console.log(this.constructor.name + "收到请求:", message);
}
public send(message?: any): void {
console.log(this.constructor.name + "上架新卡:", message);
this.mediator.relay(this, message); //请中介者转发
}
}
//具体中介者
class ConcreteShop extends Shop {
constructor() {
super()
}
}
//具体玩家1
class Fifaer1 extends Fifaer {
constructor() {
super()
}
public receive(message?: any): void {
console.log(`${message} 对于我来讲太贵了`)
}
}
//具体玩家2
class Fifaer2 extends Fifaer {
constructor() {
super()
}
public receive(message?: any): void {
console.log(`${this.constructor.name}: ${message} 对于我来讲刚恰好`)
}
}
//具体玩家3
class Fifaer3 extends Fifaer {
constructor() {
super()
}
public receive(message?: any): void {
console.log(`${this.constructor.name}: ${message} 对于我来讲太便宜了`)
}
}
let shop: Shop = new ConcreteShop();
let f1: Fifaer = new Fifaer1();
let f2: Fifaer = new Fifaer2();
let f3: Fifaer = new Fifaer3();
shop.register('Ronaldo',f1);
shop.register('Messi',f2);
shop.register('Torres',f3);
f1.send('托雷斯的巅峰卡: 1E ep');
// Fifaer1上架新卡: 托雷斯的巅峰卡: 1E ep
// Fifaer2: 托雷斯的巅峰卡: 1E ep 对于我来讲刚恰好
// Fifaer3: 托雷斯的巅峰卡: 1E ep 对于我来讲太便宜了
复制代码
JS版本
var Shop = /** @class */ (function () {
function Shop() {
//存储
this.fifaers = {};
}
//注册
Shop.prototype.register = function (name, fifaer) {
if (this.fifaers[name]) {
console.error(name + "\u540D\u79F0\u5DF2\u5B58\u5728");
}
else {
this.fifaers[name] = fifaer;
fifaer.setMedium(this);
}
};
//转发
Shop.prototype.relay = function (fifaer, message) {
var _this = this;
Object.keys(this.fifaers).forEach(function (name) {
if (_this.fifaers[name] !== fifaer) {
_this.fifaers[name].receive(message);
}
});
};
return Shop;
}());
//抽象玩家类
var Fifaer = /** @class */ (function () {
function Fifaer() {
}
Fifaer.prototype.setMedium = function (mediator) {
this.mediator = mediator;
};
Fifaer.prototype.receive = function (message) {
console.log(this.constructor.name + "收到请求:", message);
};
Fifaer.prototype.send = function (message) {
console.log(this.constructor.name + "上架新卡:", message);
this.mediator.relay(this, message); //请中介者转发
};
return Fifaer;
}());
//具体中介者
var ConcreteShop = /** @class */ (function (_super) {
__extends(ConcreteShop, _super);
function ConcreteShop() {
return _super.call(this) || this;
}
return ConcreteShop;
}(Shop));
//具体玩家1
var Fifaer1 = /** @class */ (function (_super) {
__extends(Fifaer1, _super);
function Fifaer1() {
return _super.call(this) || this;
}
Fifaer1.prototype.receive = function (message) {
console.log(message + " \u5BF9\u4E8E\u6211\u6765\u8BF4\u592A\u8D35\u4E86");
};
return Fifaer1;
}(Fifaer));
//具体玩家2
var Fifaer2 = /** @class */ (function (_super) {
__extends(Fifaer2, _super);
function Fifaer2() {
return _super.call(this) || this;
}
Fifaer2.prototype.receive = function (message) {
console.log(this.constructor.name + ": " + message + " \u5BF9\u4E8E\u6211\u6765\u8BF4\u521A\u521A\u597D");
};
return Fifaer2;
}(Fifaer));
//具体玩家3
var Fifaer3 = /** @class */ (function (_super) {
__extends(Fifaer3, _super);
function Fifaer3() {
return _super.call(this) || this;
}
Fifaer3.prototype.receive = function (message) {
console.log(this.constructor.name + ": " + message + " \u5BF9\u4E8E\u6211\u6765\u8BF4\u592A\u4FBF\u5B9C\u4E86");
};
return Fifaer3;
}(Fifaer));
var shop = new ConcreteShop();
var f1 = new Fifaer1();
var f2 = new Fifaer2();
var f3 = new Fifaer3();
shop.register('Ronaldo', f1);
shop.register('Messi', f2);
shop.register('Torres', f3);
f1.send('托雷斯的巅峰卡: 1E ep');
// Fifaer1上架新卡: 托雷斯的巅峰卡: 1E ep
// Fifaer2: 托雷斯的巅峰卡: 1E ep 对于我来讲刚恰好
// Fifaer3: 托雷斯的巅峰卡: 1E ep 对于我来讲太便宜了
复制代码
Why
What
定义:不改变现有对象结构的状况下,动态地给该对象增长一些职责(即增长其额外功能)的模式
解释:使用装饰器模式能在不改变源代码的基础上,对源代码的功能进行拓展
Game:鬼泣4中,但丁在暴揍各大领主得到许多道具,所以解锁几种战斗模式,如枪神模式
How
TS版本
@blademasterDecoration
@gunslingerDecoration
@tricksterDecoration
@royalGuardDecoration
class Dante {
sayHi() {
console.log(`My name is: Dante`)
}
}
// 剑圣模式
function blademasterDecoration(target: any){
target.prototype.blademaster = function(){console.log('I am blademaster!')}
}
// 枪神模式
function gunslingerDecoration(target){
target.prototype.gunslinger = function(){console.log('I am gunslinger!')}
}
// 骗术师模式
function tricksterDecoration(target){
target.prototype.trickster = function(){console.log('I am trickster!')}
}
// 皇家守卫模式
function royalGuardDecoration(target){
target.prototype.royalGuard = function(){console.log('I am royalGuard!')}
}
let dante: Dante = new Dante();
dante.blademaster();
dante.gunslinger();
dante.trickster();
dante.royalGuard();
// I am blademaster!
// I am gunslinger!
// I am trickster!
// I am royalGuard!
复制代码
JS版本
var Dante = /** @class */ (function () {
function Dante() {
}
Dante.prototype.sayHi = function () {
console.log("My name is: Dante");
};
Dante = __decorate([
blademasterDecoration,
gunslingerDecoration,
tricksterDecoration,
royalGuardDecoration
], Dante);
return Dante;
}());
// 剑圣模式
function blademasterDecoration(target) {
target.prototype.blademaster = function () { console.log('I am blademaster!'); };
}
// 枪神模式
function gunslingerDecoration(target) {
target.prototype.gunslinger = function () { console.log('I am gunslinger!'); };
}
// 骗术师模式
function tricksterDecoration(target) {
target.prototype.trickster = function () { console.log('I am trickster!'); };
}
// 皇家守卫模式
function royalGuardDecoration(target) {
target.prototype.royalGuard = function () { console.log('I am royalGuard!'); };
}
var dante = new Dante();
dante.blademaster();
dante.gunslinger();
dante.trickster();
dante.royalGuard();
// I am blademaster!
// I am gunslinger!
// I am trickster!
// I am royalGuard!
复制代码
Why
What
定义:将一个类的接口转换成客户但愿的另一个接口,使得本来因为接口不兼容而不能一块儿工做的那些类能一块儿工做
解释:简单来讲就是打补丁,兼容一些旧的接口
Game:LOL中卡兹克登场时,空中能够释放w秒人,号称飞天螳螂。由于过于变态与英雄平衡机制不兼容,因而给他打了个补丁,W
自己改动不大只是不容许在空中释放了。
How
W
能够空中释放,而且有治疗和减速的效果W
TS版本
interface TargetW{
request(): void;
}
// 源接口
class OriginW{
normalRequest(): void{
console.log('个人w可以治疗、减速');
}
flyRequest(): void{
console.log('个人w能在空中释放');
}
}
class AdapterW extends OriginW implements TargetW{
constructor(){
super();
}
request(): void{
console.log('取消了w在空中释放的机制');
this.normalRequest();
}
}
let target: TargetW = new AdapterW();
target.request();
// 取消了w在空中释放的机制
// 个人w可以治疗、减速
复制代码
JS版本
var OriginW = /** @class */ (function () {
function OriginW() {
}
OriginW.prototype.normalRequest = function () {
console.log('个人w可以治疗、减速');
};
OriginW.prototype.flyRequest = function () {
console.log('个人w能在空中释放');
};
return OriginW;
}());
var AdapterW = /** @class */ (function (_super) {
__extends(AdapterW, _super);
function AdapterW() {
return _super.call(this) || this;
}
AdapterW.prototype.request = function () {
console.log('取消了w在空中释放的机制');
this.normalRequest();
};
return AdapterW;
}(OriginW));
var target = new AdapterW();
target.request();
// 取消了w在空中释放的机制
// 个人w可以治疗、减速
复制代码
Why
What
定义:有时又叫做部分-总体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-总体”的关系,使用户对单个对象和组合对象具备一致的访问性。
解释:将对象之间的关系以🌲的形式进行表现
Game:最终幻想13中技能树的结构,每一个加点方向为树干,每一个技能点为树叶
How
TS版本
interface SkillTree{
add(st: SkillTree): void;
operation(): void;
}
class SkillDirection implements SkillTree{
private children: SkillTree[] = [];
constructor(private name: string){}
add(node: SkillTree): void{
this.children.push(node);
}
operation(): void{
console.log(`你选择${this.name}方向的技能树`)
this.children.forEach((x: SkillTree) => x.operation())
}
}
class SkillPoint implements SkillTree{
constructor(private name: string){}
add(node: SkillTree): void{};
operation(): void{
console.log(`你已学习技能点 ${this.name}`)
}
}
let tree1: SkillTree = new SkillDirection('治疗');
let tree2: SkillTree = new SkillDirection('伤害');
let leaf1: SkillTree = new SkillPoint('全体加血');
let leaf2: SkillTree = new SkillPoint('单体攻击');
tree2.add(leaf2);
tree1.add(tree2);
tree1.add(leaf1);
tree1.operation();
// 你选择治疗方向的技能树
// 你选择伤害方向的技能树
// 你已学习技能点 单体攻击
// 你已学习技能点 全体加血
复制代码
JS版本
var SkillDirection = /** @class */ (function () {
function SkillDirection(name) {
this.name = name;
this.children = [];
}
SkillDirection.prototype.add = function (node) {
this.children.push(node);
};
SkillDirection.prototype.operation = function () {
console.log("\u4F60\u9009\u62E9" + this.name + "\u65B9\u5411\u7684\u6280\u80FD\u6811");
this.children.forEach(function (x) { return x.operation(); });
};
return SkillDirection;
}());
var SkillPoint = /** @class */ (function () {
function SkillPoint(name) {
this.name = name;
}
SkillPoint.prototype.add = function (node) { };
;
SkillPoint.prototype.operation = function () {
console.log("\u4F60\u5DF2\u5B66\u4E60\u6280\u80FD\u70B9 " + this.name);
};
return SkillPoint;
}());
var tree1 = new SkillDirection('治疗');
var tree2 = new SkillDirection('伤害');
var leaf1 = new SkillPoint('全体加血');
var leaf2 = new SkillPoint('单体攻击');
tree2.add(leaf2);
tree1.add(tree2);
tree1.add(leaf1);
tree1.operation();
// 你选择治疗方向的技能树
// 你选择伤害方向的技能树
// 你已学习技能点 单体攻击
// 你已学习技能点 全体加血
复制代码
Why
What
定义:对有状态的对象,把复杂的“判断逻辑”提取到不一样的状态对象中,容许状态对象在其内部状态发生改变时改变其行为
解释:不使用if-else | switch-case
进行判断,而是经过传入状态对象进行状态切换
Game:只狼中苇名一心的三个状态,完美虐杀玩家
How
TS版本
interface State{
change(context: WeiMingYiXin): void;
}
class StateOne implements State{
change(context: WeiMingYiXin): void{
console.log('苇名弦一郎阶段');
}
}
class StateTwo implements State{
change(context: WeiMingYiXin): void{
console.log('剑圣苇名一心阶段');
}
}
class StateThree implements State{
change(context: WeiMingYiXin): void{
console.log('雷电法王苇名一心阶段');
}
}
class WeiMingYiXin{
constructor(private state: State){};
setState(state: State): void{
this.state = state;
}
request(): void{
this.state.change(this);
}
}
let ctx: WeiMingYiXin = new WeiMingYiXin(new StateOne());
ctx.request();
ctx.setState(new StateTwo());
ctx.request();
ctx.setState(new StateThree());
ctx.request();
// 苇名弦一郎阶段
// 剑圣苇名一心阶段
// 雷电法王苇名一心阶段
复制代码
JS版本
var StateOne = /** @class */ (function () {
function StateOne() {
}
StateOne.prototype.change = function (context) {
console.log('苇名弦一郎阶段');
};
return StateOne;
}());
var StateTwo = /** @class */ (function () {
function StateTwo() {
}
StateTwo.prototype.change = function (context) {
console.log('剑圣苇名一心阶段');
};
return StateTwo;
}());
var StateThree = /** @class */ (function () {
function StateThree() {
}
StateThree.prototype.change = function (context) {
console.log('雷电法王苇名一心阶段');
};
return StateThree;
}());
var WeiMingYiXin = /** @class */ (function () {
function WeiMingYiXin(state) {
this.state = state;
}
;
WeiMingYiXin.prototype.setState = function (state) {
this.state = state;
};
WeiMingYiXin.prototype.request = function () {
this.state.change(this);
};
return WeiMingYiXin;
}());
var ctx = new WeiMingYiXin(new StateOne());
ctx.request();
ctx.setState(new StateTwo());
ctx.request();
ctx.setState(new StateThree());
ctx.request();
// 苇名弦一郎阶段
// 剑圣苇名一心阶段
// 雷电法王苇名一心阶段
复制代码
Why
What
定义:是一种为访问类提供一个建立一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能获得同族的不一样等级的产品的模式结构
解释:类比于现实中的工厂,抽象工厂能够生产多个品类的产品
Game:红色警惕中,盟军和苏军的空军工厂和陆军工厂分别能产出不一样的军备和士兵
How
TS版本
interface AbstractAirForce{
create(): void;
}
interface AbstractGroundForce{
create(): void;
}
interface AbstractGroup{
createAirForce(): AbstractAirForce;
createGroundForce(): AbstractGroundForce;
}
class MAirForce implements AbstractAirForce{
create(): void{
console.log('战斗机已创立')
}
}
class MGroundForce implements AbstractGroundForce{
create(): void{
console.log('幻影坦克已创立')
}
}
class SAirForce implements AbstractAirForce{
create(): void{
console.log('飞艇已创立')
}
}
class SGroundForce implements AbstractGroundForce{
create(): void{
console.log('犀牛坦克已创立')
}
}
class MGroup implements AbstractGroup{
createAirForce(): AbstractAirForce{
return new MAirForce();
}
createGroundForce(): AbstractGroundForce{
return new MGroundForce();
}
}
class SGroup implements AbstractGroup{
createAirForce(): AbstractAirForce{
return new SAirForce();
}
createGroundForce(): AbstractGroundForce{
return new SGroundForce();
}
}
let mGroup: AbstractGroup = new MGroup();
let sGroup: AbstractGroup = new SGroup();
mGroup.createAirForce().create();
mGroup.createGroundForce().create();
sGroup.createGroundForce().create()
sGroup.createGroundForce().create();
// 战斗机已创立
// 幻影坦克已创立
// 犀牛坦克已创立
// 犀牛坦克已创立
复制代码
JS版本
var MAirForce = /** @class */ (function () {
function MAirForce() {
}
MAirForce.prototype.create = function () {
console.log('战斗机已创立');
};
return MAirForce;
}());
var MGroundForce = /** @class */ (function () {
function MGroundForce() {
}
MGroundForce.prototype.create = function () {
console.log('幻影坦克已创立');
};
return MGroundForce;
}());
var SAirForce = /** @class */ (function () {
function SAirForce() {
}
SAirForce.prototype.create = function () {
console.log('飞艇已创立');
};
return SAirForce;
}());
var SGroundForce = /** @class */ (function () {
function SGroundForce() {
}
SGroundForce.prototype.create = function () {
console.log('犀牛坦克已创立');
};
return SGroundForce;
}());
var MGroup = /** @class */ (function () {
function MGroup() {
}
MGroup.prototype.createAirForce = function () {
return new MAirForce();
};
MGroup.prototype.createGroundForce = function () {
return new MGroundForce();
};
return MGroup;
}());
var SGroup = /** @class */ (function () {
function SGroup() {
}
SGroup.prototype.createAirForce = function () {
return new SAirForce();
};
SGroup.prototype.createGroundForce = function () {
return new SGroundForce();
};
return SGroup;
}());
var mGroup = new MGroup();
var sGroup = new SGroup();
mGroup.createAirForce().create();
mGroup.createGroundForce().create();
sGroup.createGroundForce().create();
sGroup.createGroundForce().create();
// 战斗机已创立
// 幻影坦克已创立
// 犀牛坦克已创立
// 犀牛坦克已创立
复制代码
Why
What
一个对象(方法)只作一件事情。
How
Why
What
设计程序时,应当减小对象之间的交互,避免出现a.foo1(b).foo2(c).foo3(d)
的状况出现
若是两个对象之间没必要直接通讯,那么这两个对象就不要发生直接联系,而是引入一个第三方对象,来承担这些对象之间的通讯做用
How
Why
What
添加新功能的时候,可使用增长代码的方式,可是不容许改动程序的源代码
How
if-else | switch-case
等大量条件分支语句Why
bug
而引入更多的bug
,而新增代码是一种更加明智的选择《JS设计模式与开发实践》