Shu-How Zの小窝

Loading...

设计模式---结构型

结构型

适配器模式

`将一个类的接口转化为另外一个接口.解决使类之间接口不兼容问题

优点
1.可以让任何两个没有关联的类一起运行。
2.提高了类的复用性、透明度、以及灵活性
3.适配对象,适配库,适配数据

缺点
额外对象的创建,非直接调用,存在一定的开销
过多的使用适配器模式,会让系统变得零乱,不易整体把控。
非必要用适配器模式,就重构最好,若用的话,文档完善

场景
整合第三方SDK diy $.axjax
封装旧接口  vue.computed


适配器与代理模式相似
适配器模式: 提供一个不同的接口
代理模式: 提供一模一样的接口

class Person{
    getName(){
        return "John";
    }
}
class Adapter{
    constructor(person){
        this.person = person;
    }
    getFullName(){
        return this.person.getName();
    }
}
let person = new Person();
let adapter = new Adapter(person);
console.log(adapter.getFullName());

装饰器模式

装饰者模式在不更改源代码情况下,对其进行职责添加。相比于继承装饰器的更轻巧。
通俗的讲我们给心爱的手机上贴膜,带手机壳,贴纸,这些就是对手机的装饰。
优点
	装饰类和被装饰类它们之间可以相互独立发展,不会相互耦合,
    装饰器模式是继承的一个替代模式,它可以动态的扩展一个实现类的功能。
缺点
	多层的装饰会增加复杂度
class Phone{
    create(){
        console.log("Phone created");
    }
}

class Decorator{
    constructor(phone){
        this.phone = phone;
    }
    create(){
        this.phone.create();
        this.addPhoneBox();
        this.addPhonePicker();
    }
    addPhoneBox(){
        console.log("Phone box added");
    }
    addPhonePicker(){
        console.log("Phone picker added");
    }
}
let phone = new Phone();
let decorator = new Decorator(phone);
decorator.create();   

代理模式

优点
	代理模式能将代理对象与被调用对象分离,降低了系统的耦合度。
	之间起到一个中介作用,这样可以起到保护目标对象的作用
	代理对象可以扩展目标对象的功能
	通过修改代理对象就可以了,符合开闭原则;
缺点
	处理请求速度可能有差别,非直接访问存在开销
    
// 员工类
class Staff {
  constructor(task) {
    this.task = task;
  }
  applyFor(target){
    target.receiveAplyFor(this.task)
  }
}
// 秘书类 中间人 代理
class Secretary {
  constructor() {
    this.leader=new Leader();
  }
  receiveAplyFor(task) {
    this.leader.receiveAplyFor(task);
  }
}
// 领导类
class Leader{
    receiveAplyFor(task) {
        console.log('批准: ' + task);
    }
}
const staff = new Staff('升职加薪')
staff.applyFor(new Secretary()) // 批准:升职加薪    

外观模式

外观模式本质就是封装交互,隐藏系统的复杂性,提供一个可以访问的接口。
由一个将子系统一组的接口集成在一起的高层接口,以提供一个一致的外观,减少外界与多个子系统之间的直接交互,从而更方便的使用子系统。
优点
	减少系统相互依赖。
	提高灵活性。
	提高了安全性
缺点
	不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
    
// 外观模式
function addEvent(el,type,fn){
    if(el.addEventlistener){// 高级游览器添加事件DOM API
        el.addEventlistener(type,fn,false)
    }else if(el.attachEvent){// 低版本游览器的添加事件API
        el.attachEvent(`on${type}`,fn)
    }else {//其他
        el[type] = fn
    }
}

二层金字塔
	1
2	2	2

桥接模式

桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化。
优点
	有助于独立地管理各组成部分, 把抽象化与实现化解耦
	提高可扩充性
缺点
	大量的类将导致开发成本的增加,同时在性能方面可能也会有所减少。
    桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
//桥接模式(Bridge)
class color{
    constructor(name){
        this.name = name;
    }
}
class shape{
    constructor(name,color){
        this.name = name;
        this.color = color;
    }
    show(){
        console.log(this.name + this.color.name);
    }
}
let red = new color('红色');
let yellow = new color('黄色');
let circle = new shape('圆形',red);
let triangle = new shape('三角形',yellow);
circle.show();
triangle.show();

组合模式

组合模式
组合模式就是由一些小的子对象构建出的更大的对象,而这些小的子对象本身可能也是由多个孙对象组合而成的。
组合模式将对象组合成树状结构,以表示“部分-整体”的层次结构。除了用来表示树状结构之外,组合模式的另一个好处就是通过对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性。

缺点
如果通过组合模式创建了太多的对象,那么这些对象可能会让系统负担不起。

优点
高层模块调用简单,节点可以自由添加

// 组合模式
class Train{
    create(){
        console.log('创建火车票订单')
    }
}
class Hotal{
    create(){
        console.log('创建酒店订单')
    }
}
class TotalOrder{
    constructor(){
        this.orderList = [];
    }
    add(order){
        this.orderList.push(order);
        return this;
    }
    create(){
        this.orderList.forEach(order=>{
            order.create();
        })
        return this;
    }
}
let totalOrder = new TotalOrder();
// 可以在购票网站买车票同时也订房间
totalOrder.add(new Train()).add(new Hotal()).create();

享元模式

运用共享技术有效地支持大量细粒度对象的复用。
享元模式的关键是如何区分内部状态和外部状态
	内部状态:可以被对象共享,通常不会改变的称为内部状态
	外部状态:取决于具体的场景,根据具体的场景变化,并且不能被共享的称为外部状态
优点
	大大减少对象的创建,降低系统的内存,使效率提高。
缺点
	提高了系统的复杂度,需要分离出外部状态和内部状态,而且外部状态具有固有化的性质, 不应该随着内部状态的变化而变化,否则会造成系统的混乱
    
let id = 0
// 定义内部状态
class Upload {
  constructor(uploadType) {
    this.uploadType = uploadType
  }
  // 点击删除时 小于3000直接删除,大于3000通过confirm提示弹窗删除。
  delFile(id) {
    uploadManager.setExternalState(id,this)
    if(this.fileSize < 3000){
      return this.dom.parentNode.removeChild(this.dom)
    }
    if(window.confirm(`确定要删除该文件吗?${this.fileName}`)){
      return this.dom.parentNode.removeChild(this.dom)
    }
  }
}
// 外部状态
class uploadManager {
  static uploadDatabase = {}
  static add(id, uploadType, fileName, fileSize) {
    const filWeightObj = UploadFactory.create(uploadType)
    const dom = this.createDom(fileName, fileSize, () => {
      filWeightObj.delFile(id)
    })
    this.uploadDatabase[id] = {
      fileName,
      fileSize,
      dom
    }
  }
  // 创建DOM 并且为button绑定删除事件。
  static createDom(fileName, fileSize, fn) {
    const dom = document.createElement('div')
    dom.innerHTML = `
      <span>文件名称:${fileName},文件大小:${fileSize}</span>
      <button class="delFile">删除</button>
    `
    dom.querySelector('.delFile').onclick = fn
    document.body.append(dom)
    return dom
  }
  static setExternalState(id, flyWeightObj) {
    const uploadData = this.uploadDatabase[id]
    for (const key in uploadData) {
      if (Object.hasOwnProperty.call(uploadData, key)) {
        flyWeightObj[key] = uploadData[key]
      }
    }
  }

}
// 定义一个工厂创建upload对象,如果其内部状态实例对象存在直接返回,反之创建保存并返回。
class UploadFactory {
  static createFlyWeightObjs = {}
  static create(uploadType) {
    if (this.createFlyWeightObjs[uploadType]) {
      return this.createFlyWeightObjs[uploadType]
    }
    return this.createFlyWeightObjs[uploadType] = new Upload(uploadType)
  }
}
// 开始加载
const startUpload = (uploadType, files)=>{
    for (let i = 0, file; file = files[i++];) {
      uploadManager.add(++id, uploadType, file.fileName, file.fileSize)
    }
}

startUpload('plugin', [
  {fileName: '1.txt',fileSize: 1000},
  {fileName: '2.html',fileSize: 3000},
  {fileName: '3.txt',fileSize: 5000}
]);
startUpload('flash', [
  {fileName: '4.txt',fileSize: 1000},
  {fileName: '5.html',fileSize: 3000},
  {fileName: '6.txt',fileSize: 5000}
]);
    
posted @ 2025-05-26 17:48  KooTeam  阅读(14)  评论(0)    收藏  举报