狀態和策略模式

  • 當一個對象的內部狀態發生改變時,會導致其行爲的改變,這看起來相是改變了對象
  • 對象有自己的狀態
  • 不同狀態下執行的邏輯不一樣
  • 明確狀態和每個狀態下執行的動作
  • 用來減少 if else子句
//狀態模式
class SuccessState{
    show(){
        console.log('high');
    }
}
class WarningState{
    show(){
        console.log('middle');
    }
}
class LowState{
    show(){
        console.log('low');
    }
}
class Battery{
    constructor(){
        this.amount = 'high';
        this.state = new SuccessState();
    }
    show(){
        this.state.show();
        if(this.amount == 'high'){
            this.amount = 'middle';
            this.state = new WarningState();
        }else if(this.amount == 'middle'){
            this.amount = 'low';
            this.state = new LowState();
        }
    }
}
let b1= new Battery();
b1.show();
b1.show();
b1.show();

 狀態模式應用場景

<div id="root"></div>
    <script>
        let likeState = {
            render(element){
                element.innerHTML = '贊'
            }
        }
        let likedState = {
            render(element){
                element.innerHTML = '取消'
            }
        }
        class Button{
            constructor(container){
                this.liked = false;//默認未點贊狀態
                this.state = likeState;
                this.element = document.createElement("button");
                container.appendChild(this.element);
                this.render()
            }
            setState(state){
                this.state = state;
                this.render();
            }
            
            render(){
                this.state.render(this.element)
            }
        }
        let button = new Button(document.body);
        button.element.addEventListener('click',()=>{
            button.setState(button.liked?likeState:likedState)
            button.liked = !button.liked;
        },false)
    </script>

狀態模式應用場景-promise(不完全應用)

class Promise{
    constructor(fn){
        this.state = 'initial';
        this.successes = [];
        this.errors = [];
        let resolve = (data)=>{
            this.state = 'fulfilled';
            this.successes.forEach(item=>item(data))
        }
        let reject = (error)=>{
            this.state = 'failed';
            this.errors.forEach(item=>item(error));
        }
        fn(resolve,reject);
    }
    then(success,error){
        this.successes.push(success);
        this.errors.push(error);
    }
}
let p = new Promise(function(resolve,reject){
    setTimeout(function(){
        let num = Math.random();
        if(num>0.5){
            resolve(num)
        }else{
            reject(num)
        }
    },500)
})
p.then((data)=>{
    console.log(data,'成功')
},(data)=>{
    console.log(data,'失敗')
})

策略模式

  • 將定義的一組算法封裝起來,使其相互之間可以替換。封裝的算法具有一定獨立性,不會隨客戶端變化而變化
  • 避免大量的if else或者 switch case
//常規寫法
class Customer{
    constructor(type){
        this.type = type;
    }
    pay(amount){
        if(this.type == 'member'){
            return amount*.9;
        }else if(this.type == 'vip'){
            return amount*.8;
        }else{
            return amount
        }
    }
}
//策略模式
class CustomerNew{
    constructor(kind){
        this.kind = kind;
    }
    pay(amount){
        return this.kind.pay(amount)
    }
}
class Normal{
    pay(amount){
        return amount;
    }
}
class Member{
    pay(amount){
        return amount*0.9;
    }
}
class Vip{
    pay(amount){
        return amount*0.8;
    }
}
let c1 = new CustomerNew(new Normal());
console.log(c1.pay(100))
c1.kind = new Member;
console.log(c1.pay(100))
c1.kind = new Vip;
console.log(c1.pay(100))

//方法2
class Customer1{
    constructor(){
        this.kind = {
            normal:function(amount){
                return amount;
            },
            member:function(amount){
                return amount*0.9
            },
            vip:function(amount){
                return amount*0.8
            }
        }
    }
    pay(kind,amount){
        return this.kind[kind](amount)
    }
}
let c= new Customer1();
console.log(c.pay('normal',100))
console.log(c.pay('member',100))
console.log(c.pay('vip',100))

策略模式應用場景

<form id="userForm">
 用戶名:<input type="text" name="username"><br/>
 密碼:<input type="text" name="password"><br/>
 手機號:<input type="text" name="mobile"><br/>
 郵箱:<input type="text" name="email"><br/>
 <input type="submit" value="提交">
</form>
<script>
let form = document.getElementById('userForm');
let validator = (function(){
  let rules = {
   notEmpty(val,msg){
	if(val===''){
	  return msg;
	}
  },
  maxLength(val,max,msg){
    if(val===''|| val.length>max){
	 return msg;
	}
  },
  minLength(val,min,msg){
	if(val===''||val.length<min){
	 return msg;
	}
  },
  isMobile(val,msg){
    if(!/1\d{10}/.test(val)){
	 return msg;
	}
  }
 }
 function addRule(name,rule){
   rules[name] = rule;
 }
 let checks = [];
 function add(ele,rule){
   checks.push(function(){
    let val = ele.value;
    let name = rule.shift();
    rule.unshift(val);
    return rules[name] && rules[name].apply(ele,rule)
  })
 };
 function start(){
   for(let i=0;i<checks.length;i++){
	 let check = checks[i];
	 let msg = check();
	 if(msg){
	  return msg;
	 }
   }
 }
 return {addRule,add,start}
})()
validator.addRule('isEmail',function(val,msg){
 if(!/.*@.*/.test(val)){
  return msg;
 }
})
form.onsubmit = function(){
 console.log(form.username)
 validator.add(form.username,['notEmpty','用戶名不能爲空'])
 validator.add(form.password,['minLength',6,'密碼長度不能少於6位'])
 validator.add(form.password,['maxLength',8,'密碼長度不能大於8位'])
 validator.add(form.mobile,['isMobile','必須輸入合法的手機號'])
 validator.add(form.email,['isEmail','請輸入合法郵箱地址'])
 let msg = validator.start();
 if(msg){
  alert(msg);
  return false;
 }
 return true;
}
</script>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章