适配器模式
// 适配器模式
interface MediaPlayer {
play(type: string, fileName: string): void;
}
interface AdvanceMediaPlayer {
playVlc?(fileName: string): void;
playMp4?(fileName: string): void;
}
class VlcPlayer implements AdvanceMediaPlayer {
playVlc(fileName: string) {
console.log("playing vlc file......." + fileName);
}
}
class Mp4Player implements AdvanceMediaPlayer {
playMp4(fileName: string) {
console.log("playing mp4 file......." + fileName);
}
}
class MediaAdapter implements MediaPlayer {
player: AdvanceMediaPlayer;
constructor(type: string) {
// 根据type 生成哪一个播放类
if (type === "vlc") {
this.player = new VlcPlayer();
} else if (type === "mp4") {
this.player = new Mp4Player();
} else {
this.player = new Mp4Player(); // 默认使用mp4player
}
}
play(type: string, fileName: string) {
// 因为特定的播放类有特定的播放方法,所以还需要再根据type调用特定的播放类
if (type === "vlc") {
if (this.player.playVlc) this.player.playVlc(fileName);
} else if (type === "mp4") {
if (this.player.playMp4) this.player.playMp4(fileName);
} else {
return null;
}
}
}
export class AudioPlayer implements MediaPlayer {
play(type: "mp3" | "mp4" | "vlc", fileName: string): boolean {
if (type === "mp3") {
console.log("播放器内置支持mp3, " + fileName + "已开始播放.");
return true;
} else if (type === "vlc" || type === "mp4") {
let ma = new MediaAdapter(type);
ma.play(type, fileName);
return true;
} else {
console.log("不支持当前格式");
return false;
}
}
}
测试文件:
import { AudioPlayer } from "../src/Adapter";
test("playing to be true", () => {
let player = new AudioPlayer();
expect(player.play("mp3", "aa.mp3")).toBe(true);
expect(player.play("mp4", "bb.mp4")).toBe(true);
expect(player.play("vlc", "cc.vlc")).toBe(true);
});
桥接模式
// 桥接模式
interface DrawApi {
draw(radius: number, x: number, y: number): string;
}
export class RedCircle implements DrawApi {
draw(radius: number, x: number, y: number) {
console.log(radius, x, y);
return "red circle";
}
}
export class GreenCircle implements DrawApi {
draw(radius: number, x: number, y: number) {
console.log(radius, x, y);
return "green circle";
}
}
abstract class Shape {
protected drawApi: DrawApi;
protected constructor(drawApi: DrawApi) {
this.drawApi = drawApi;
}
abstract draw(): string;
}
export class Circle extends Shape {
private _x: number;
private _y: number;
private _radius: number;
constructor(x: number, y: number, radius: number, drawApi: DrawApi) {
super(drawApi);
this._x = x;
this._y = y;
this._radius = radius;
}
draw() {
return this.drawApi.draw(this._radius, this._x, this._y);
}
}
测试文件:
import { Circle, RedCircle, GreenCircle } from "../src/Bridge";
test("circle shape", () => {
let redCircle = new Circle(1, 1, 1, new RedCircle());
let greenCircle = new Circle(2, 2, 2, new GreenCircle());
expect(redCircle.draw()).toContain("red");
expect(greenCircle.draw()).toContain("green");
});
建造者模式
// 建造者模式
// 从一个个简单的类组合成一个大的类。
// 食品包装接口
interface Packing {
pack(): string;
}
// 纸质包装类,专门用来包裹汉堡
class Wrapper implements Packing {
pack() {
return "Wrapper";
}
}
// 瓶子包装类,专门用来装饮料
class Bottle implements Packing {
pack() {
return "Bottle";
}
}
// 食物接口
interface Item {
name(): string;
packing(): Packing;
price(): number;
}
// 基类的好处,就是把公共的逻辑提取到基类中
// 汉堡基类
abstract class Burger implements Item {
name() {
return "Burger";
}
packing(): Packing {
return new Wrapper();
}
abstract price(): number;
}
// 饮料基类
abstract class ColdDrink implements Item {
name() {
return "ColdDrink";
}
packing(): Packing {
return new Bottle();
}
abstract price(): number;
}
// 素食汉堡
class VegBurger extends Burger {
name() {
return "VegBurger";
}
price() {
return 25;
}
}
// 鸡肉汉堡
class ChickenBurger extends Burger {
name() {
return "ChickenBurger";
}
price() {
return 50;
}
}
class Coke extends ColdDrink {
name() {
return "Coke";
}
price() {
return 30;
}
}
// 百事可乐
class Pepsi extends ColdDrink {
name() {
return "Pepsi";
}
price() {
return 35;
}
}
// 套餐
class Meal {
private _items: Item[] = [];
addItem(item: Item) {
this._items.push(item);
}
getCost() {
let cost = 0;
for (let item of this._items) {
cost += item.price();
}
return cost;
}
showItems() {
for (let item of this._items) {
console.log(`Item : ${item.name()}`);
console.log(`Packing : ${item.packing().pack()}`);
console.log(`Item : ${item.price()}`);
}
}
}
class MealBuilder {
// 准备素食套餐
prepareVegMeal() {
let meal = new Meal();
meal.addItem(new VegBurger());
meal.addItem(new Coke());
return meal;
}
// 准备非素食套餐
prepareNoteVegMeal() {
let meal = new Meal();
meal.addItem(new ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}
export { Meal, MealBuilder, VegBurger, ChickenBurger, Coke, Pepsi };
测试文件:
import {
Meal,
MealBuilder,
ChickenBurger,
VegBurger,
Coke,
Pepsi
} from "../src/Builder";
test("mealBuilder get a Meal", () => {
let mealBuilder = new MealBuilder();
let m1 = mealBuilder.prepareVegMeal();
let m2 = mealBuilder.prepareNoteVegMeal();
expect(m1 instanceof Meal).toBe(true);
expect(m2 instanceof Meal).toBe(true);
expect(m1.getCost() === new VegBurger().price() + new Coke().price()).toBe(
true
);
expect(
m2.getCost() === new ChickenBurger().price() + new Pepsi().price()
).toBe(true);
});