Head First Design Mode(12)-状态模式

2023-10-31

该系列文章系个人读书笔记及总结性内容,任何组织和个人不得转载进行商业活动!

 

状态模式: 

    状态模式和策略模式是“双胞胎,在出生时才分开”;

    策略模式是围绕可以互换的算法来创建成功业务的;

    状态模式则是通过改变对象内部的状态来帮助对象控制自己的行为;

 

状态转换实例——工作的糖果机:

    我们需要糖果机控制如下流程,而且设计需要有弹性、好维护(未来可能增加更多行为);        

    

简单分析下:

    这张图像是一张状态图,每个圆圈都是一个状态,每个箭头都是状态的转换;

    这里的每一个状态都代表机器不同的配置以某种方式行动,需要某些动作将目前的状态转换到另一个状态;

    比如,“没有25分钱”的状态下,放进25分钱的硬币,就会进入“25分钱”的状态,即状态的转换;

    而且,对于任何一个可能的多国内说,我们都要检查,看看我们所处的状态和动作是否合适;

 

状态机 101:

    我们来看下实现状态机(state machine)的简单介绍;

1)首先,找出所有的状态;

2)创建一个实例变量来持有目前的状态,定义每个状态的值;

    比如,我们可以用 final static int SOLD_OUT = 0;//来表示糖果售罄的状态;(其他状态都是不同的整数值)

3)现在,将所有系统中可以发生的动作整合起来;

    任何一个动作都会造成状态的转换;

4)创建一个类,作用就是一个状态机;

    这里我们使用了一个通用的技巧:对对象内的状态建模——通过创建一个实例变量来持有状态值,并在方法内书写条件代码来处理不同的状态;

 

我们开始实现-糖果机:

【Code GumballMachine.java】

public class GumballMachine{
    //all state
    final static int SOLD_OUT = 0;
    final static int NO_QUARTER = 1;
    final static int HAS_QUARTER = 2;
    final static int SOLD = 3;
    
    //default sold out
    int state = SOLD_OUT;
    int count  = 0;//gumbal count 
    
    public GumballMachine(int count){
        this.count = count;
        if(count >0){
            state = NO_QUARTER;
        }
    }
    
    //投入25分钱 
    public void insertQuarter(){
        if (state == HAS_QUARTER){
            System.out.print("- you have insert a quarter -\n");
        }else if (state == NO_QUARTER){
            state = HAS_QUARTER;
            System.out.print("- you inserted a quarter -\n");
        }else if (state == SOLD_OUT){
            System.out.print("- the machine is sold out -\n");
        }else if (state == SOLD){
            System.out.print("- please wait, we are giving you a gumbal -\n");
        }
    }
    
    //退回25分钱
    public void ejectQuarter(){
        if (state == HAS_QUARTER){
            System.out.print("- quarter returned -\n");
            state = NO_QUARTER;
        }else if (state == NO_QUARTER){
            System.out.print("- you have not inserted a quarter -\n");
        }else if (state == SOLD_OUT){
            System.out.print("- do not this, you have not inserted a quarter -\n");
        }else if (state == SOLD){
            System.out.print("- Sorry, you already turned the crank -\n");
        }
    }
    
    //转动曲柄
    public void turnCrank(){
        if (state == HAS_QUARTER){
            System.out.print("- turned -\n");
            state = SOLD;
            dispense();
        }else if (state == NO_QUARTER){
            System.out.print("- you turned, but you have not inserted a quarter -\n");
        }else if (state == SOLD_OUT){
            System.out.print("- gumbal has sold out -\n");
        }else if (state == SOLD){
            System.out.print("- turning twice no use -\n");
        }
    }
    
    //发放糖果
    public void dispense(){
        if (state == HAS_QUARTER){
            System.out.print("- No gumbal dispensed -\n");
        }else if (state == NO_QUARTER){
            System.out.print("- you need pay first -\n");
        }else if (state == SOLD_OUT){
            System.out.print("- No gumbal dispensed -\n");
        }else if (state == SOLD){
            System.out.print("- gumbal is comming -\n");
            count = count - 1;
            if (count == 0){
                System.out.print("- Sorry, out of gumbals -\n");
                state = SOLD_OUT;
            }else{
                state = NO_QUARTER;
            }
        }
    }
    
    //other methods
    public String toString() {
        String str = "";
        if (state == HAS_QUARTER){
            str = "- Machine state: " + "HAS_QUARTER, count = " +count+ "-\n";
        }else if (state == NO_QUARTER){
            str = "- Machine state: " + "NO_QUARTER, count = " +count + "-\n";
        }else if (state == SOLD_OUT){
            str = "- Machine state: " + "SOLD_OUT, count = " +count + "-\n";
        }else if (state == SOLD){
            str = "- Machine state: " + "SOLD, count = " +count + "-\n";
        }
        return str;
    }
}

测试运行:

【Code GumballMachineDrive.java】

public class GumballMachineDrive{
    
    public static void main(String[] args){
        GumballMachine gumbalMachine = new GumballMachine(2);
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
    
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
        
    }
    
}

 


上面是我们实现的状态机101,而且通过我们的测试,运行是正常的;

但是,我们收到了新的需求:

    当曲柄被转动时,有10%的几率掉下来两颗糖果;

 

此时我们能体会到一开始设计的糖果机并不容易扩展:

    加上一个新的状态,就必须在每个方法中加入一个新的条件判断来处理赢家状态;

    我们需要重构这份代码,以便我们能容易地维护和维修他;

 

遵循“封装变化”原则:

    将每个状态的行为都放在各自的类中,那么每个状态只要实现它自己的动作就可以了;

    糖果机只需要委托给代表当前状态的状态对象;

 

新的设计:

    将状态对象封装在各自的类中,然后在动作发生时委托给当前状态;

1)首先,定义一个State接口,每个动作都有一个对应的方法;

2)然后为机器中的每个状态实现状态类,这些类将负责在对应的状态下进行机器的行为;

3)最后,拜托条件代码,取而代之的是,将动作委托到状态类;

 

在实现之后,我们会发现,优化的版本不仅遵守了设计原则,实际上我们还实现了状态模式;

 

状态模式的状态机:

    创建State接口,所有的状态都必须实现这个接口;

    接口定义的方法直接映射到糖果机上可能发生的动作;

    将设计中的每个状态都封装成一个类,每个都实现State接口;

 

我们先不增加10%概率赢的状态和操作,只是添加下重填这个事件(售完状态 可以通过重填 转换到 需要25分钱的状态),实现如下:

【Code GumballMachineDrive.java】

public class GumballMachineDrive{
    
    public static void main(String[] args){
        GumballMachine gumbalMachine = new GumballMachine(2);
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
    
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.refill(5);
        System.out.print(gumbalMachine + "\n");

        
    }
    
}

【Code GumballMachine.java】

public class GumballMachine{

    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;
    

    State state = soldOutState;
    int count  = 0;//gumbal count 
    
    public GumballMachine(int numberGumballs){
        
        soldOutState = new SoldOutState(this);
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        
        this.count = numberGumballs;
        if(numberGumballs >0){
            state = noQuarterState;
        }
    }
    
    //投入25分钱 
    public void insertQuarter(){
        state.insertQuarter();
    }
    
    //退回25分钱
    public void ejectQuarter(){
       state.ejectQuarter();
    }
    
    //转动曲柄
    public void turnCrank(){
        state.turnCrank();
        state.dispense();
    }
    
    //发放糖果
    public void dispense(){
        state.dispense();
    }
    
    //重填 
    public void refill(int numberGumball){
        this.count = numberGumball;
        state.refill(numberGumball);
    }
    
    //辅助方法 
    void releaseBall(){
        System.out.print("发了一颗糖 \n");
        if (count != 0){
            count = count - 1;
        }
    }
    
    void setState(State state){
        this.state = state;
    }
    State getState(){
        return state;
    }
    int getCount(){
        return count;
    }
    State getSoldOutState(){
        return soldOutState;
    }
    State getNoQuarterState(){
        return noQuarterState;
    }
    State getHasQuarterState(){
        return hasQuarterState;
    }
    State getSoldState(){
        return soldState;
    }
    
    //other methods
    public String toString() {
        String str = "";
        if (state == hasQuarterState){
            str = "- Machine state: " + "HAS_QUARTER, count = " +count+ "-\n";
        }else if (state == noQuarterState){
            str = "- Machine state: " + "NO_QUARTER, count = " +count + "-\n";
        }else if (state == soldOutState){
            str = "- Machine state: " + "SOLD_OUT, count = " +count + "-\n";
        }else if (state == soldState){
            str = "- Machine state: " + "SOLD, count = " +count + "-\n";
        }
        return str;
    }
}

【Code State.java】

public interface State{
    //投入25分钱
    public void insertQuarter();
    
    //退回25分钱
    public void ejectQuarter();
    
    //转动曲柄
    public void turnCrank();
    
    //发放糖果
    public void dispense();
    
    //重填
    public void refill(int numberGumball);
    
}

【Code NoQuarterState.java】

public class NoQuarterState implements State{
    GumballMachine gumballMachine;
    
    public NoQuarterState(GumballMachine gumballMachine){
        this.gumballMachine = gumballMachine;
    }
    
    //投入25分钱
    public void insertQuarter(){
        gumballMachine.setState(gumballMachine.getHasQuarterState());
        System.out.print("-已投入 25分钱  \n");
    }
    
    //退回25分钱
    public void ejectQuarter(){
        System.out.print("-还没 投入 25分钱  \n");
    }
    
    //转动曲柄
    public void turnCrank(){
        System.out.print("-还没 投入 25分钱  \n");
    }
    
    //发放糖果
    public void dispense(){
        System.out.print("-还没 投入 25分钱  \n");
    }
    
    //重填
    public void refill(int numberGumball){
        System.out.print("-还有糖果 \n");
    }
    
    
}

【Code HasQuarterState.java】

public class HasQuarterState implements State{
    GumballMachine gumballMachine;
    
    public HasQuarterState(GumballMachine gumballMachine){
        this.gumballMachine = gumballMachine;
    }
    
    //投入25分钱
    public void insertQuarter(){
        System.out.print("-已投入 25分钱  \n");
    }
    
    //退回25分钱
    public void ejectQuarter(){
        gumballMachine.setState(gumballMachine.getNoQuarterState());
        System.out.print("-退还 25分钱  \n");
    }
    
    //转动曲柄
    public void turnCrank(){
        gumballMachine.setState(gumballMachine.getSoldState());
        System.out.print("-转动曲柄  \n");
    }
    
    //发放糖果
    public void dispense(){
        System.out.print("-糖果还没出来   \n");
    }
    
    //重填
    public void refill(int numberGumball){
        System.out.print("-还有糖果 无法 重填 \n");
    }
    
    
}

【Code SoldState.java】

public class SoldState implements State{
    GumballMachine gumballMachine;
    
    public SoldState(GumballMachine gumballMachine){
        this.gumballMachine = gumballMachine;
    }
    
    //投入25分钱
    public void insertQuarter(){
        System.out.print("-请稍后 我们正在发发糖   \n");
    }
    
    //退回25分钱
    public void ejectQuarter(){
        System.out.print("-请稍后 我们正在发发糖   \n");
    }
    
    //转动曲柄
    public void turnCrank(){
        System.out.print("-请稍后 我们正在发发糖   \n");
    }
    
    //发放糖果
    public void dispense(){
        gumballMachine.releaseBall();
        if (gumballMachine.getCount() > 0){
            gumballMachine.setState(gumballMachine.getNoQuarterState());
        }else{
            gumballMachine.setState(gumballMachine.getSoldOutState());
            System.out.print("-糖果空了   \n");
        }
    }
    
    //重填
    public void refill(int numberGumball){
        System.out.print("-糖果 在售中  \n");
    }
    
    
}

【Code SoldOutState.java】

public class SoldOutState implements State{
    GumballMachine gumballMachine;
    
    public SoldOutState(GumballMachine gumballMachine){
        this.gumballMachine = gumballMachine;
    }
    
    //投入25分钱
    public void insertQuarter(){
        System.out.print("-糖果空了   \n");
    }
    
    //退回25分钱
    public void ejectQuarter(){
        System.out.print("-糖果空了   \n");
    }
    
    //转动曲柄
    public void turnCrank(){
        System.out.print("-糖果空了   \n");
    }
    
    //发放糖果
    public void dispense(){
        System.out.print("-糖果空了   \n");
    }
    
    //重填
    public void refill(int numberGumball){
        gumballMachine.setState(gumballMachine.getNoQuarterState());
        System.out.print("-糖果 已重填  \n");
    }
    
    
}

 

检查一下我们现在做的:

    将每个状态的行为局部化到他自己的类中;

    将容易产生问题的if语句删除,方便维护;

    让每一个状态“对修改关闭”,让糖果机“对扩展开放”;

 


 

定义状态模式:

    状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类;

 

这个模式将状态封装成为独立的类,并将动作委托到代表当前状态的对象;我们是在使用组合通过简单引用不同的状态对象来造成改变的假象;

 

类图:

    

 

我们发现这个类图和策略模式的类图一样:

    以状态模式而言,我们将一群行为封装在状态对象中,context的行为随时可委托到那些状态对象中的一个;

    当前状态在状态对象集合中游走改变,以反映出context内部的状态;

    但是,context的客户对于状态对象了解不多,甚至浑然不觉;

    而以策略模式而言,客户通常主动指定Context所要组合的策略对象是哪一个;策略模式让我们有弹性,能够在运行时改变策略;

 

    一般来说,我们把策略模式想成是除了继承之外的一种弹性替代方案;如果你使用继承定义了一个类的行为,你将被这个行为困住,甚至要修改它都很难;有了策略模式,你可以通过组合不同的对象来改变行为;

    我们把状态模式想成是不用在context中放置许多条件判断的替代方案;通过将行为包装进状态对象中,你可以通过在context内简单地改变状态对象来改变context的行为;

 

注意:

    一般来讲,当状态改变时固定的时候,就适合放在Context中;然而,当转换是更动态的时候,通常会放在状态类中;

    客户也不会直接改变Context的状态;

    不持有自己内部状态的状态对象是可以在多个上下文实例之间共享的;

    对于State既可以是接口,也可以是抽象类,当没有共同功能可以放进抽象类时,就使用接口;

 


 

10%概率抽奖的问题解决:

    接下来我们编码实现,验证可扩展性;

 

这里我们只列出修改的类:

【Code WinnerState.java】

public class WinnerState implements State{
    GumballMachine gumballMachine;
    
    public WinnerState(GumballMachine gumballMachine){
        this.gumballMachine = gumballMachine;
    }
    
    //投入25分钱
    public void insertQuarter(){
        System.out.print("-请稍后 我们正在发发糖   \n");
    }
    
    //退回25分钱
    public void ejectQuarter(){
        System.out.print("-请稍后 我们正在发发糖   \n");
    }
    
    //转动曲柄
    public void turnCrank(){
        System.out.print("-请稍后 我们正在发发糖   \n");
    }
    
    //发放糖果
    public void dispense(){
        System.out.print("-Winner!   \n");
        gumballMachine.releaseBall();
        if (gumballMachine.getCount() == 0){
            gumballMachine.setState(gumballMachine.getSoldOutState());
        }else{
            gumballMachine.releaseBall();
            if (gumballMachine.getCount() > 0){
                gumballMachine.setState(gumballMachine.getNoQuarterState());
            }else{
                gumballMachine.setState(gumballMachine.getSoldOutState());
            }
        }
    }
    
    //重填
    public void refill(int numberGumball){
        System.out.print("-请稍后 我们正在发发糖   \n");
    }
    
    
}

【Code GumballMachine.java】

public class GumballMachine{

    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;
    State winnerState;//add
    

    State state = soldOutState;
    int count  = 0;//gumbal count 
    
    public GumballMachine(int numberGumballs){
        
        soldOutState = new SoldOutState(this);
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        winnerState = new WinnerState(this);//add
        
        this.count = numberGumballs;
        if(numberGumballs >0){
            state = noQuarterState;
        }
    }
    
    //投入25分钱 
    public void insertQuarter(){
        state.insertQuarter();
    }
    
    //退回25分钱
    public void ejectQuarter(){
       state.ejectQuarter();
    }
    
    //转动曲柄
    public void turnCrank(){
        state.turnCrank();
        state.dispense();
    }
    
    //发放糖果
    public void dispense(){
        state.dispense();
    }
    
    //重填 
    public void refill(int numberGumball){
        this.count = numberGumball;
        state.refill(numberGumball);
    }
    
    //辅助方法 
    void releaseBall(){
        System.out.print("发了一颗糖 \n");
        if (count != 0){
            count = count - 1;
        }
    }
    
    void setState(State state){
        this.state = state;
    }
    State getState(){
        return state;
    }
    int getCount(){
        return count;
    }
    State getSoldOutState(){
        return soldOutState;
    }
    State getNoQuarterState(){
        return noQuarterState;
    }
    State getHasQuarterState(){
        return hasQuarterState;
    }
    State getSoldState(){
        return soldState;
    }
    State getWinnerState(){//add
        return winnerState;
    }
    
    
    //other methods
    public String toString() {
        String str = "";
        if (state == hasQuarterState){
            str = "- Machine state: " + "HAS_QUARTER, count = " +count+ "-\n";
        }else if (state == noQuarterState){
            str = "- Machine state: " + "NO_QUARTER, count = " +count + "-\n";
        }else if (state == soldOutState){
            str = "- Machine state: " + "SOLD_OUT, count = " +count + "-\n";
        }else if (state == soldState){
            str = "- Machine state: " + "SOLD, count = " +count + "-\n";
        }
        return str;
    }
}

【Code HasQuarterState.java】

import java.util.Random;//add

public class HasQuarterState implements State{
    Random randomWinner = new Random();//add
    GumballMachine gumballMachine;
    
    public HasQuarterState(GumballMachine gumballMachine){
        this.gumballMachine = gumballMachine;
    }
    
    //投入25分钱
    public void insertQuarter(){
        System.out.print("-已投入 25分钱  \n");
    }
    
    //退回25分钱
    public void ejectQuarter(){
        gumballMachine.setState(gumballMachine.getNoQuarterState());
        System.out.print("-退还 25分钱  \n");
    }
    
    //转动曲柄
    public void turnCrank(){
        System.out.print("-转动曲柄  \n");
        int winner = randomWinner.nextInt(10);//add
        if ((winner == 0) && (gumballMachine.getCount() > 1)){
            gumballMachine.setState(gumballMachine.getSoldState());
        }else{
            gumballMachine.setState(gumballMachine.getWinnerState());
        }
    }
    
    //发放糖果
    public void dispense(){
        System.out.print("-糖果还没出来   \n");
    }
    
    //重填
    public void refill(int numberGumball){
        System.out.print("-还有糖果 无法 重填 \n");
    }
    
    
}

【Code GumballMachineDrive.java】

public class GumballMachineDrive{
    
    public static void main(String[] args){
        GumballMachine gumbalMachine = new GumballMachine(6);
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
    
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.insertQuarter();
        gumbalMachine.turnCrank();
        
        System.out.print(gumbalMachine + "\n");
        
        gumbalMachine.refill(5);
        System.out.print(gumbalMachine + "\n");

        
    }
    
}

运行结果:

 

dispense()方法即使是没有25分钱,句柄转动也总是被调用;我们可以轻易地修改这部分:让turnCrank()返回一个布尔值,或者引入异常;

 

状态:封装基于状态的行为,并将行为委托到当前状态;

策略:将可以互换的行为封装起来,然后使用委托的方法,决定使用哪一个行为;

模板方法:由子类决定如何实现算法中的某些步骤

 

总结:

1.状态模式允许一个对象基于内部状态而拥有不同的行为

2.和程序状态机(PSM)不同,状态模式用类代表状态;

3.Context会将行为委托给当前状态对象;

4.通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了;

5.状态模式和策略模式有相同的类图,但是他们的意图不同;

6.策略模式通常会用行为或算法来配置Context类;

7.状态模式允许Context随着状态的改变而改变行为;

8.状态转换可以由State类或Context类控制;

9.使用状态模式通常会导致设计中类的数目大量增加;

10.状态类可以被多个Context实例共享;

 

OO基础:

    抽象;

    封装

    继承;

    多态;

OO原则:

    封装变化

    多用组合,少用继承

    针对接口编程,不针对实现编程

    为交互对象之间的松耦合设计而努力;

    类应该对扩展开放,对修改关闭;

    依赖抽象,不要依赖具体类;

    只和朋友交谈(最少知识原则);

    别找我,我会找你(好莱坞原则:由超类主控一切,需要的时候自然会去调用子类);

    类应该只有一个改变的理由(单一职责原则);

OO模式:

    策略模式:定义算法族,分别封装起来,让他们之间互相替换,此模式让算法的变化独立于使用算法的客户;

    观察者模式:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新;

    装饰者模式:动态地将责任附加到对象上;想要扩展功能,装饰者提供有别于继承的另一种选择;

    简单工厂模式;

    工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个;工厂方法让类把实例化推迟到子类;

    抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确具体的类;

    单件模式:确保一个类只有一个实例,并提供全局访问点;

    命令模式:将请求封装成对象,这可以让你使用不同的请求,队列或者日志请求来参数化其他对象;命令模式也支持撤销操作;

    适配器模式:将一个类的接口转换成客户期待的另一个接口,适配器让原来不兼容的类可以合作无间;

    外观模式:提供了一个统一的接口,用来访问子系统中的一群接口;外观模式定义了高层接口,让子系统更容易使用;

    模板方法模式:在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中;模板方法使得子类可以在不改变算法结构的情况下,重新定义/捕获算法中的某些步骤;

    迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示;

    组合模式:允许你将对象组成树形结构来表现整体/部分的层次结构;组合能让客户以一致的方式处理个别对象和对象组合;

    ——状态模式:允许对象在内部状态改变时改变他的行为,对象看起来好像修改了它的类;

    

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Head First Design Mode(12)-状态模式 的相关文章

  • 设计模式浅析-适配器模式

    前言 2017年悄悄的来了 无声无息的以至于我都还没好好缅怀一下荒诞的2016 不得不说 2016没能通过努力达到应该有的程度 看样子目标还是要有的 那就先设定一个小目标吧 设计模式 当你学会了设计模式 就要忘记设计模式 辉哥 适配器模式
  • 21 个简洁的 JavaScript单行代码技巧

    JavaScript 发展至今已经变得越来越强大 且广泛用于前端和后端开发 作为一名前端程序员 不断的学习精进技巧 了解JS的最新发展也是非常必要的 而简洁的一行代码示例就是很好的方法 今天 我们有 21 个JavaScript单行代码技巧
  • Java创建型模式之原型模式

    原型模式 所谓原型模式 就是以一个对象为原型 返回这个对象的克隆 而不是创建一个新的对象 原型对象的优点 在Java中创建一个新对是昂贵和资源密集型 原型对象有助于创建更好性能的重复对象 原型模式的核心就是克隆 克隆又分为浅克隆 深克隆 1
  • Java 动态代理和静态代理 详解(结合代码实列)

    文章目录 Java 动态代理和静态代理的区别 下面是一个结合代码示例 运行上述代码 输出如下 总结 Java 动态代理和静态代理的区别 动态代理和静态代理是两种不同的代理模式 它们在代理对象的创建和使用方式上有所不同 静态代理 静态代理是在
  • 05_Vue基础入门

    vue的作用 渐进式的前端框架 里面的框架按需获取 vue特点 1 解耦视图和数据 2 双向数据绑定 3 可复用的组件 常用的按钮和表格 4 前端路由数据 页面跳转 5 状态管理 6 虚拟DOM 引入方式 1 使用CDN连接引入 加载速度更
  • 软件设计模式(一)

    本章学习主要参照Datawhale开源学习及 大话设计模式 本项目结合 大话设计模式 这本书 总结了各种设计模式的基本概念 知识点和适用场景 先通过书中的案例 介绍了23种设计模式及其相关的代码示例 项目中有多种语言代码示例 本文主要采用P
  • 注入多个实现类【JAVA】(设计模式之策略模式)项目实际场景【Spring boot】

    文章目录 业务场景 策略模式的概念 代码示例 1 创建一个接口类 2 创建接口类的实现类 3 创建脚手架 box类 4 最后创建一个实现工厂类 MsgBeanFactory 5 测试代码 6 输出结果 总结 业务场景 最近有一个场景消息发送
  • vue3对echarts的二次封装之按需加载

    欢迎点击领取 前端面试题进阶指南 前端登顶之巅 最全面的前端知识点梳理总结 分享一个使用比较久的 效果展示 1 echarts是我们后台系统中最常用的数据统计图形展示 外界对它的二次封装也不计层数 2 在业务代码内每次的初始dom和绑定se
  • java设计模式——工厂方法模式(Factory Method Pattern)

    简单工厂模式虽然简单 但也受到很大限制 扩展性太差 当系统中需要引入新产品时 由于静态工厂方法通过所传入参数的不同来创建不同的产品 这必定要修改工厂类的源代码 将违背 开闭原则 如何实现增加新产品而不影响已有代码 工厂方法模式应运而生 本文
  • Java之美[从菜鸟到高手演变]之设计模式四

    在阅读过程中有任何问题 请及时联系 egg 邮箱 xtfggef gmail com 微博 http weibo com xtfggef 转载请说明出处 http blog csdn net zhangerqing 其实每个设计模式都是很重
  • Java设计模式-迪米特法则

    迪米特法则 Low Of Demeter 定义 一个对象应该对其他对象保持最少的了解 问题由来 类与类之间的关系越密切 耦合度越大 当一个类发生改变时 对另一个类的影响也越大 解决方案 尽量降低类与类之间的耦合 自从我们接触编程开始 就知道
  • 细说设计模式七大原则(6):开闭原则

    2 8 1 基本介绍 英文名 Open Closed Principle OCP 定义 一个软件实体如类 模块和函数应该对扩展开放 对修改关闭 开闭原则是编程中最基础 最重要的设计原则 一个软件实体如类 模块和函数应该对扩展开放 对提供方
  • Gof23设计模式之模板方法模式

    1 定义 定义一个操作中的算法骨架 而将算法的一些步骤延迟到子类中 使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤 2 结构 模板方法 Template Method 模式包含以下主要角色 抽象类 Abstract Clas
  • JAVA设计模式(二)工厂模式与观察者模式

    工厂模式 工厂模式顾名思义则是类似于一个工厂制造产品的模式 如富士康需要制造自己的产品 而同类产品有多种 如手机有各个品牌和型号一样 明白了工厂模式的含义 我们来想想这个模式具体是怎么回事 首先需要的是一个工厂于是就需要一个Factory类
  • 跟我学Java设计模式第4天:结构型模式大全

    5 结构型模式 5 6 组合模式 5 6 1 概述 对于这个图片肯定会非常熟悉 上图我们可以看做是一个文件系统 对于这样的结构我们称之为树形结构 在树形结构中可以通过调用某个方法来遍历整个树 当我们找到某个叶子节点后 就可以对叶子节点进行相
  • 【TS第三讲】完善TS开发环境

    文章目录 写在前面 ts node nodemon nodemon文件类型 nodemon文件范围 写在最后 写在前面 探索TypeScript世界 驭Vue3 Ts潮流 开启前端之旅 欢迎来到前端技术的精彩世界 无论你是刚刚踏入编程大门的
  • 【JAVA设计模式】之桥接模式(BridgePattern)

    桥接模式的作用是将两样东西连接起来 比如桥梁把河的两岸连接起来 桥接模式把 类的功能层次结构 和 类的实现层次结构 连接起来 类的层次结构 类的功能层次 父类通过定义抽象方法来定义接口API 类的实现层次 子类通过实现具体方法来实现接口AP
  • C++设计模式-State状态模式

    State状态模式作用 当一个对象的内在状态改变时允许改变其行为 这个对象看起来像是改变了其类 UML图如下 State类 抽象状态类 定义一个接口以封装与Context的一个特定状态相关的行为 ConcreteState类 具体状态 每一
  • 设计模式——State(状态)模式

    目录 前言 1 定义 2 适用性 3 结构 3 1 结构图 3 2 参与者 4 应用举例 4 1 State TcpState 4 2 Context TcpConnection 4 3 ConcreteState ListeningTcp
  • 新手也能看懂的【前端自动化测试入门】

    2024软件测试面试刷题 这个小程序 永久刷题 靠它快速找到工作了 刷题APP的天花板 CSDN博客 文章浏览阅读2 3k次 点赞85次 收藏11次 你知不知道有这么一个软件测试面试的刷题小程序 里面包含了面试常问的软件测试基础题 web自

随机推荐

  • 热区的使用方法

    1 如图所示 热区的位置是在元件库中 这样的一个标识 2 热区的使用经常会搭配一些比较小的文字或者图片等区域 只要是在热区中 随便点击哪一个地方都是属于这个区域 3 我们做了几个页面 样式不同 4 如图 我们创建一个热区在02的选区中 5
  • python + selenium实现巨潮资讯网指定范围年报下载

    大家好 第一次写文章 紧张滴捏 这段时间在做课设 课设里需要下载沪市600000到601000号的年报原文做数字化关键词的词频分析 想着用程序帮我批量下载一下 但是找了一下貌似没有类似的代码 就写了一个应用selenium库来做模拟下载的p
  • 各类打印机驱动官网下载安装

    前言概述 找驱动很简单 但是网上有时候找起来有点费劲呢 不安全 目前市面上打印机驱动搜索软件好用的基本都要付费 或者不全 比如下图这个就是付费的 常用的打印机品牌 惠普 HP 佳能 Canon 爱普生 Epson 京瓷 Kyocera 三星
  • 二流计算机学校,学校可以是二流的,但你不是

    我每天都会看大家在微博里给我的留言 时常看到深夜 私信的 每一条都看 问的最多的一种问题 是这么开头的 我的学校不好 或者 我是一个来自二 三 本学校的学生 我该怎么办 我不知道怎么回答 因为我不觉得来自一个二流的学校就应该过着二流的生活
  • C语言实现队列(链表实现)

    队列 Queue 也是运算受限的线性表 是一种先进先出 First In First Out 简称 FIFO 的线性表 只允许在表的一端进行插入 而在另一端进行删除 队首 front 允许进行删除的一端称为队首 队尾 rear 允许进行插入
  • 浅析Linux内核中的链表

    1 内核中的链表 linux内核链表与众不同 他不是把将数据结构塞入链表 而是将链表节点塞入数据 在2 1内核中引入了官方链表 从此内核中所有的链表使用都采用此链表 千万不要在重复造车轮子了 链表实现定义在
  • 第五届蓝桥杯Java A组决赛试题

    1 标题 海盗分金币 有5个海盗 相约进行一次帆船比赛 比赛中天气发生突变 他们被冲散了 恰巧 他们都先后经过途中的一个无名的荒岛 并且每个人都信心满满 觉得自己是第一个经过该岛的人 第一个人在沙滩上发现了一堆金币 他把金币分成5等份 发现
  • STM32CubeMX驱动MPU6050模块

    文章目录 1 MPU6050模块简介 2 MPU6050重要寄存器介绍 2 1 数字低通滤波器配置寄存器CONFIG 2 2 采样率分频寄存器SMPRT DIV 2 3 加速度计配置寄存器ACCEL CONFIG 2 4 角速度计配置寄存器
  • 区别:OrderedDict vs dict

    OrderedDict 和 dict 是两种字典类型 都用于存储键值对 key value pairs dict 是Python的内置字典类型 它是无序的 即它不会按照元素插入的顺序来保存键值对 当你通过键来访问 dict 中的值时 Pyt
  • sqoop query时单双引号选用以及$CONDITION使用的探究

    这段时间碰见了一个奇怪的sqoop导入问题 我的业务目标是想将postgresql库里的某张表内的数据导入到hive里 而且在导入的时候需要做一步查询 但在导入的时候 围绕着 CONDITION 这个参数 会有不同的运行结果 有的报错 有的
  • MySQL基础架构与日志详解

    一 MySQL基础架构 MySQL可以分为Server层和存储引擎层两部分 Server层包括连接器 查询缓存 分析器 优化器 执行器等 涵盖MySQL的大多数核心服务功能 以及所有的内置函数 如日期 时间 数学和加密函数等 所有跨存储引擎
  • 软件需求之DFD图

    DFD图是一种以数据和数据的封闭性为基础 从问题空间到某种表示的映射方法 是一种结构化分析方法 DFD图在软件的需求分析中发挥着不可替代的作用 DFD图在软考中是必考的内容 在软件工程中也是一个非常中要的图 下面是我结合网上的资料和自己的所
  • Linux系统里压缩PDF文件大小

    sudo apt get install ghostscript gs sDEVICE pdfwrite dCompatibilityLevel 1 4 dPDFSETTINGS screen dNOPAUSE dQUIET dBATCH
  • JavaFX 控件 ImageView

    ImageView 支持格式 BMP GIF JPEG PNG 加载图片 如果设置了 requestedXXX 尺寸 ImageView中 设置 FitXXX 尺寸是基于requestedXXX 尺寸缩放 Image image new I
  • Linux & Docker常用命令

    目录 一 Docker服务相关命令 二 镜像相关命令 查看镜像 查看本地所有的镜像 搜索镜像 从网络中查找需要的镜像 拉取镜像 删除镜像 三 容器相关命令 查看容器 创建容器 进入容器 启动容器 停止容器 重启应用 删除容器 查看容器信息
  • OpenCV教程——加载、修改、保存图像

    1 颜色空间 颜色空间 也称彩色模型 又称彩色空间或彩色系统 本质上 彩色模型是坐标系统和子空间的阐述 位于系统的每种颜色都有单个点表示 RGB 红绿蓝 是依据人眼识别的颜色定义出的空间 可表示大部分颜色 但在科学研究中一般不采用RGB颜色
  • ARouter 源码分析

    ARouter基本使用 在开始分析源码之前 先了解一下ARoute如何使用的 使用ARoute可以概括为以下3步 项目中引入ARouter 及配置 初始化ARouter 开始使用 下面详细的看下每一步怎么操作 项目中引入ARouter及配置
  • 计算机一级2010的试题,全国计算机等级考试一级office2010试题

    计算机一级是要求考生对基础的计算机知识进行掌握 下面给大家整理了全国计算机等级考试一级office2010试题 欢迎阅读 全国计算机等级考试一级office2010试题 选择题答案 1 5 C A D B B 6 10 B C D B D
  • Qt项目实战2:图片查看器QImageViewer

    在博文Qt学习笔记2 QMainWindow和QWidget的区别中介绍了使用空的Qt项目创建带有菜单栏 工具栏的界面 这里 使用一个简单的图片查看器项目 来熟悉一下Qt的图片显示和基本操作 该项目实现的主要功能 实现图片的打开 关闭 居中
  • Head First Design Mode(12)-状态模式

    该系列文章系个人读书笔记及总结性内容 任何组织和个人不得转载进行商业活动 状态模式 状态模式和策略模式是 双胞胎 在出生时才分开 策略模式是围绕可以互换的算法来创建成功业务的 状态模式则是通过改变对象内部的状态来帮助对象控制自己的行为 状态