JS设计模式-状态模式
1.原代码
假设我们期望给按钮绑定事件以实现关灯->弱光->强光->关灯的效果
按照一般性思维我们得到了以下代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button id="button"></button>
</body>
<script>
class Light {
constructor(button) {
this.button = button;
this.currentState = "off";
}
initButton() {
this.button.onclick = ()=>{
this.pressButton()
};
}
pressButton() {
if (this.currentState === "off") {
console.log("弱光");
this.currentState = "weakLight";
} else if (this.currentState === "weakLight") {
console.log("强光");
this.currentState = "strongLight";
} else {
console.log("无光/关灯");
this.currentState = "off";
}
}
}
let light = new Light(button)
light.initButton()
</script>
</html>
2.原代码存在的问题
1.不符合开放封闭原则
2.胖函数
3.状态切换不明显
4.切换关系不明确
3.采用状态模式进行改进
于是我们便得到了以下代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button id="button"></button>
</body>
<script>
class Light{
constructor(button){
this.button = button
this.offLight = new OffLight(this)
this.weakLight = new WeakLight(this)
this.strongLight = new StrongLight(this)
this.currentStatus = new OffLight(this)
}
setStatus(newStatus){
this.currentStatus = newStatus
}
initButton() {
this.button.onclick = ()=>{
this.currentStatus.changeState()
};
}
}
class WeakLight{
constructor(light){
this.light = light
}
changeState(){
console.log('强光');
this.light.setStatus(this.light.strongLight)
}
}
class StrongLight{
constructor(light){
this.light = light
}
changeState(){
console.log('无光');
this.light.setStatus(this.light.offLight)
}
}
class OffLight{
constructor(light){
this.light = light
}
changeState(){
console.log('弱光');
this.light.setStatus(this.light.weakLight)
}
}
let light = new Light(button)
light.initButton()
</script>
</html>
*4.采用责任链模式对原代码进行改进
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button id="button">switch</button>
</body>
<script>
function chain(fn,status){
this.status = status
this.fn = fn
this.next = null
}
function offLight(light){
if(light.status === 'offLight'){
console.log('弱光');
light.status = 'weakLight'
}else{
this.next.fn.call(this.next,light)
}
}
function weakLight(light){
if(light.status === 'weakLight'){
console.log('强光');
light.status = 'strongLight'
}else{
this.next.fn.call(this.next,light)
}
}
function strongLight(light){
if(light.status === 'strongLight'){
console.log('无光');
light.status = 'offLight'
}else{
this.next.fn.call(this.next,light)
}
}
chain.prototype.setNextChain = function(chain){
this.next = chain
}
chain.prototype.changeStatus = function(){
this.fn()
}
let light = new chain(function(){this.next.fn.call(this.next,this)},'offLight')
let offlight = new chain(offLight,'offLight')
let weaklight = new chain(weakLight,'weakLight')
let stronglight = new chain(strongLight,'strongLight')
light.setNextChain(offlight)
offlight.setNextChain(weaklight)
weaklight.setNextChain(stronglight)
button.onclick = ()=>{
light.changeStatus()
}
</script>
</html>