迷思 2017-12-10
作者简介 远峰 蚂蚁金服数据前端
继前文Typescript玩转设计模式 之 创建型模式之后,本周带来的是系列文章之二,讲解的是4种结构性模式:
结构性模式分为7种,本文先讲解其中四种,剩余3种下一篇文章再进行讨论~
将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
适配器模式由以下角色构成:


电源插座是220V的,但手机充电时只需要5V,因此我们需要一个适配器让手机能在220V插座上充电。
// 适配器有2种实现模式,类模式和对象模式
// 目标接口
interface Voltage5vInterface {
connect5v(): void;
}
// 被适配类
class Voltage220v {
connect220v() {
console.log('接通220V电源,');
}
}
// 客户类,保存对适配器对象的引用关系,通过访问适配器对象来间接使用被适配对象
// 这里,手机充电时只需要知道适配器对象的5V接口就能调用被适配的220V插座来充电了
class Phone {
private voltage5v: Voltage5vInterface;
constructor(voltage5v: Voltage5vInterface) {
this.voltage5v = voltage5v;
}
charge(): void {
this.voltage5v.connect5v();
console.log('已经接通电源,手机开始充电');
}
}
// 类适配器
// Voltage220v是被适配的类,接口跟最终要求不一致
// Voltage5vInterface包含想要提供的接口
// 因此"继承"被适配的类,"实现"想要支持的接口
class ClassPowerAdapter extends Voltage220v implements Voltage5vInterface {
connect5v(): void {
this.connect220v();
console.log('将220V电源转化为5v电源,');
}
}
function classAdapterDemo() {
const adapter = new ClassPowerAdapter();
const phone = new Phone(adapter);
phone.charge();
}
classAdapterDemo();
// 对象适配器
// 适配器中持有被适配类的对象的引用
class InstancePowerAdapter implements Voltage5vInterface {
private voltage220v: Voltage220v;
constructor(voltage220v: Voltage220v) {
this.voltage220v = voltage220v;
}
connect5v(): void {
this.voltage220v.connect220v();
console.log('将220V电源转化为5v电源,');
}
}
function instanceAdapterDemo() {
const voltage220v = new Voltage220v();
const adapter = new InstancePowerAdapter(voltage220v);
const phone = new Phone(adapter);
phone.charge();
}
instanceAdapterDemo();同一个接口适配不同的类
电脑有个USB接口,可以插入华为手机或iphone的数据线
// 电脑的USB接口
interface ComputerInterface {
usb(): void;
}
// 华为手机,有自己的数据接口
class HuaweiPhone {
huaweiInterface(): void {
console.log('华为手机的数据接口');
}
}
// iphone,有自己的数据接口
class Iphone {
iphoneInterface(): void {
console.log('苹果手机的数据接口');
}
}
// 华为手机数据线适配器
class HuaweiDataWireAdapter extends HuaweiPhone implements ComputerInterface {
usb(): void {
console.log('使用华为数据线连接');
super.huaweiInterface();
}
}
// iphone手机数据线适配器
class IphoneDataWireAdapter extends Iphone implements ComputerInterface {
usb(): void {
console.log('使用苹果数据线连接');
super.iphoneInterface();
}
}
function commonAdapterDemo() {
const computer1 = new HuaweiDataWireAdapter();
computer1.usb();
const computer2 = new IphoneDataWireAdapter();
computer2.usb();
}
commonAdapterDemo();将抽象部分与他的实现部分分离,使他们都可以独立地变化。
桥接模式包含以下角色:

// 汽车是一个维度,有多种不同的车型
abstract class AbstractCar {
abstract run(): void;
}
// 路是一个维度,有多种不同的路
abstract class AbstractRoad {
car: AbstractCar;
abstract snapshot(): void;
}
/**
* 汽车和路两个维度
* 桥接就是一个维度的类中引用了另一个维度的对象,但只关心接口不关心是哪个具体的类
* 从而实现两个维度独立变化
*/
class SpeedRoad extends AbstractRoad {
constructor(car: AbstractCar) {
super();
this.car = car;
}
snapshot(): void {
console.log('在高速公路上');
this.car.run();
}
}
class Street extends AbstractRoad {
constructor(car: AbstractCar) {
super();
this.car = car;
}
snapshot(): void {
console.log('在市区街道上');
this.car.run();
}
}
class Car extends AbstractCar {
run(): void {
console.log('开着小汽车');
}
}
class Bus extends AbstractCar {
run(): void {
console.log('开着公共汽车');
}
}
function carRunOnRoadDemo(): void {
// 在高速公路上,开着小汽车
const car = new Car();
const speedRoad = new SpeedRoad(car);
speedRoad.snapshot();
// 在市区街道上,开着公共汽车
const bus = new Bus();
const street = new Street(bus);
street.snapshot();
}
carRunOnRoadDemo();
/**
* 人,汽车和路三个维度
*/
abstract class Person {
road: AbstractRoad;
abstract see(): void;
}
class Man extends Person {
constructor(road: AbstractRoad) {
super();
this.road = road;
}
see(): void {
console.log('男人看到');
this.road.snapshot();
}
}
class Woman extends Person {
constructor(road: AbstractRoad) {
super();
this.road = road;
}
see(): void {
console.log('女人看到');
this.road.snapshot();
}
}
function personSeeCarOnRoadDemo() {
// 男人看到 在市区街道上 开着小汽车
const car = new Car();
const street = new Street(car);
const man = new Man(street);
man.see();
}
personSeeCarOnRoadDemo();将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
组合模式包含以下角色:

// 抽象类 人,提供战斗接口
abstract class Human {
name: string;
constructor(name: string) {
this.name = name;
}
abstract fight(): void;
}
// 士兵类,战斗操作是自己加入战斗
class Soldier extends Human {
fight() {
console.log(`${this.name} 准备加入战斗`);
}
}
// 指挥官类,战斗操作是递归召集自己的下属,集合部队
class Commander extends Human {
soldiers: Set<Soldier>;
constructor(name: string) {
super(name);
this.soldiers = new Set<Soldier>();
}
add(soldier: Soldier) {
this.soldiers.add(soldier);
}
remove(soldier: Soldier) {
this.soldiers.delete(soldier);
}
fight() {
console.log(`${this.name} 开始召集属下`);
this.soldiers.forEach(soldier => soldier.fight());
console.log(`${this.name} 部队集结完毕`);
}
}
// 在使用组合模式时,所有对象都有'fight'方法,因此不需要关心对象是士兵还是指挥官,即不需要关心是单个对象还是组合对象
function battleDemo() {
const soldier1 = new Soldier('soldier1');
const soldier2 = new Soldier('soldier2');
const soldier3 = new Soldier('soldier3');
const soldier4 = new Soldier('soldier4');
const subCommander1 = new Commander('subCommander1');
subCommander1.add(soldier1);
subCommander1.add(soldier2);
const subCommander2 = new Commander('subCommander2');
subCommander2.add(soldier3);
subCommander2.add(soldier4);
const chiefCommander = new Commander('chiefCommander');
chiefCommander.add(subCommander1);
chiefCommander.add(subCommander2);
chiefCommander.fight();
}
battleDemo();动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
装饰模式包含以下角色:

// 抽象构件——可视化组件
class VisualComponent {
draw(): void {
console.log('绘制一个组件');
}
}
// 装饰器基类,装饰可视化组件
class Decorator extends VisualComponent {
protected component: VisualComponent;
constructor(component: VisualComponent) {
super();
this.component = component;
}
draw(): void {
this.component.draw();
}
}
// 带边框的装饰器
class BorderDecorator extends Decorator {
protected width: number;
constructor(component: VisualComponent, borderWidth: number) {
super(component);
this.width = borderWidth;
}
private drawBorder(): void {
console.log(`绘制宽度为${this.width}的边框`);
}
draw() {
this.drawBorder();
this.component.draw();
}
}
// 带滚动条的装饰器
class ScrollDecorator extends Decorator {
private drawScrollBar(): void {
console.log('绘制滚动栏');
}
draw(): void {
this.drawScrollBar();
this.component.draw();
}
}
// 绘制一个带滚动条和边框的组件
function decoratorDemo() {
const component = new VisualComponent();
const finalComponent = new BorderDecorator(new ScrollDecorator(component), 1);
finalComponent.draw();
}
decoratorDemo();typeof不能指向Component类本文介绍了前4种结构型模式,对后续模式感兴趣的同学可以关注专栏或者发送简历至'chaofeng.lcf####alibaba-inc.com'.replace('####', '@'),欢迎有志之士加入~
原文地址:https://juejin.im/post/5a2d16325188252da0535d73
运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算。以上实例中 7、5 和 12 是操作数。关系运算符用于计算结果是否为 true 或者 false。逻辑运算符用于测定变量或值之间的逻辑。