# 十四.模版方法模式

  • 模版方法模式在一个方法中定义一个算法的骨架,而将一些步骤的实现延迟到子类中
  • 模版方法使得子类可以在不改变算法结构的情况下,重新定义算法中某些步骤的具体实现
  • 一般有两部分组成,第一部分是抽象父类,第二部分是具体的实现子类
  • 好莱坞原则,子类放弃了控制权,改由父类来调用
    • 发布订阅
    • 回调函数

# 1.类图

# 2.代码

class Person {
  dinner(){
    this.buy()
    this.cook()
    this.eat()
  }
  buy()
  cook()
  eat()
}
class Xiaomin extends Person {
  buy(){
    console.log('买黄瓜')
  }
  cook(){
    console.log('拍黄瓜')
  }
  eat(){
    console.log('吃黄瓜')
  }
}
let x = new Xiaomin()
x.dinner()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 3.场景

# 3.1 提示框

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <link rel="stylesheet" href="3.css" />
  </head>
  <body>
    <script src="3.js"></script>
    <script>
      let dialog = new ConfirmDialog({
        title: "标题",
        content: "内容",
      });
    </script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Dialog{
    constructor(options) {
        this.title = options.title||'标题';
        this.content = options.content||'内容';
        this.onConfirm = options.onConfirm||this.hide;
        this.onCancel = options.onCancel||this.hide;
        this.init();
        this.initEventHandler();
    }
    init() {
        this.panel=document.createElement('div');
        this.panel.className='dialog';

        this.titleP=document.createElement('p');
        this.titleP.innerHTML=this.title;
        this.panel.appendChild(this.titleP);

        this.contentP=document.createElement('p');
        this.contentP.innerHTML=this.content;
        this.panel.appendChild(this.contentP);

        this.confirmBtn=document.createElement('button');
        this.confirmBtn.className='button confirm-button';
        this.confirmBtn.innerHTML='确定';
        this.panel.appendChild(this.confirmBtn);

        this.cancelBtn=document.createElement('button');
        this.cancelBtn.className='button cancel-button';
        this.cancelBtn.innerHTML='取消';
        this.panel.appendChild(this.cancelBtn);

        document.body.appendChild(this.panel);
    }
    inithttp://image.bubuko.com/info/201807/20180712173511381297.pngntListener('click',() => {
            this.onConfirm();
            this.hide();
        });
        this.cancelBtn.addEventListener('click',() => {
            this.onCancel();
            this.hide();
        });
    }
    show() {
        this.panel.style.display='block';
    }
    hide() {
        this.panel.style.display='none';
    }
}

class ContentDialog extends Dialog{
    init() {
        super.init();
        this.titleP.parentNode.removeChild(this.titleP);
    }
}

class ConfirmDialog extends Dialog{
    init() {
        super.init();
        this.cancelBtn.parentNode.removeChild(this.cancelBtn);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
.dialog{
    width:400px;
    height:300px;
    position: absolute;
    padding:20px;
    top:50%;
    left:50%;
    margin-left:-200px;
    margin-top:-150px;
    border:1px solid#000;
    background-color: #EEE;
    border-radius: 5px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.dialog button{
    width:100px;
    height:30px;
    position: absolute;
    border: none;
    outline: none;

}
.dialog .confirm-button {
    right:140px;
    bottom:20px;
}
.dialog .cancel-button {
    right:20px;
    bottom:20px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34