侠客岛的含笑
2018-10-20 18:08:26浏览 2199
适配器
- 旧接口格式和使用者不兼容
- 中间加一个适配转换接口
- 验证
- 例子
装饰器
- 为对象添加新功能
- 不改变其原有的结构和功能
- 场景
- ES7装饰器
core-decorators
第三方库 lib
- babel-plugin-transform-decorators-legacy
- 验证
- 将现有对象和装饰器进行分离,两者独立存在
- 符合开放封闭原则
@testable(true)
class MyTestableClass {
// ...
}
function testable(isDec) {
return function(target) {
target.isDec = isDec;
}
}
alert(MyTestableClass.isTestable) // true
其实就是相当于
MyTestable = testable(MyTestable) || MyTestable
混合
function mixins(...list) {
return function (target) {
Object.assign(target.prototype, ...list)
}
}
const Foo = {
foo() { alert('foo') }
}
@mixins(Foo)
class MyClass {}
let obj = new MyClass();
obj.foo() // 'foo'
装饰方法 例
function readonly(target, name, descriptor){
// descriptor对象原来的值如下
// {
// value: specifiedFunction,
// enumerable: false,
// configurable: true,
// writable: true
// };
descriptor.writable = false;
return descriptor;
}
class Person {
constructor() {
this.first = 'A'
this.last = 'B'
}
@readonly
name() { return `${this.first} ${this.last}` }
}
var p = new Person()
console.log(p.name())
p.name = function () {} // 这里会报错,因为 name 是只读属性
function log(target, name, descriptor) {
var oldValue = descriptor.value;
descriptor.value = function() {
console.log(`Calling ${name} with`, arguments);
return oldValue.apply(this, arguments);
};
return descriptor;
}
class Math {
@log
add(a, b) {
return a + b;
}
}
const math = new Math();
const result = math.add(2, 4);
console.log('result', result);
core-decorators
import { readonly } from 'core-decorators'
class Person {
@readonly
name() {
return 'zhang'
}
}
let p = new Person()
alert(p.name())
// p.name = function () { /*...*/ } // 此处会报错
废弃装饰器
import { deprecate } from 'core-decorators';
class Person {
@deprecate
facepalm() {}
@deprecate('We stopped facepalming')
facepalmHard() {}
@deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' })
facepalmHarder() {}
}
let person = new Person();
person.facepalm();
// DEPRECATION Person#facepalm: This function will be removed in future versions.
person.facepalmHard();
// DEPRECATION Person#facepalmHard: We stopped facepalming
person.facepalmHarder();
// DEPRECATION Person#facepalmHarder: We stopped facepalming
//
// See http://knowyourmeme.com/memes/facepalm for more details.
UML类图
class Circle{
draw(){
console.Log('画一个圆形’)
}
class Decorator {
constructor(circle){
this.circle=circle
}
draw(){
this.circle.draw()
this.setRedBorder(circle)
}
setRedBorder(circle){
console.log(设置红色边框)
}
}
//测试代码
let circle=new Circle()
circle.draw()
let dec=new Decorator(circle)
dec.draw()
代理模式
- 使用者无权访问目标对象
- 中间加代理,通过代理做授权和控制
- 例子
- 场景
- 网页事件代理
- jQuery $.proxy
- ES6 Proxy
UML图
class ReadImg {
constructor(fileName){
this.fileName=fileName
this.loadFromDisk()//初始化即从硬盘中加载,模拟
}
display(){
console.log('display...'+this.fileName)
}
loadFromDisk(){
console.Log('loading...'+this.fileName)
}
}
class ProxyImg {
constructor(fileName){
this.realImg=new ReadImg(fileName)
}
display() {
this.realImg.display()
}
// test
let proxyImg=new ProxyImg('1.png')
proxyImg.display()
// 明星 ES6 Proxy
let star = {
name: '张XX',
age: 25,
phone: '13910733521'
}
// 经纪人
let agent = new Proxy(star, {
get: function (target, key) {
if (key === 'phone') {
// 返回经纪人自己的手机号
return '18611112222'
}
if (key === 'price') {
// 明星不报价,经纪人报价
return 120000
}
return target[key]
},
set: function (target, key, val) {
if (key === 'customPrice') {
if (val < 100000) {
// 最低 10w
throw new Error('价格太低')
} else {
target[key] = val
return true
}
}
}
})
// 主办方
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)
// 想自己提供报价(砍价,或者高价争抢)
agent.customPrice = 150000
// agent.customPrice = 90000 // 报错:价格太低
console.log('customPrice', agent.customPrice)
代理模式vs 适配器模式 装饰器模式 对比
- 适配器模式:提供一个不同的接口(如不同版本的插头)
- 代理模式:提供一模一样的接口
- 装饰器模式:扩展功能,原有功能不变且可直接使用
- 代理模式:显示原有功能,但是经过限制或者阉割之后的
外观模式
- 为子系统中的一组接口提供了一个高层接口
- 使用者使用这个高层接口
- 示例
- 验证
- 不符合单一职责原则和开放封闭原则,因此谨慎使用,不可滥用