美文网首页
《设计模式》之复合模式(MVC)

《设计模式》之复合模式(MVC)

作者: 魅猫之 | 来源:发表于2020-07-04 16:22 被阅读0次

    复合模式:就是将多种设计模式融合在一起,实现一个更高阶的功能,一个非常经典的复合模式就是MVC。

    MVC模式在过去的十几年里,使用频率非常高,尤其是前后端尚未分离的时候,类似的JSP、PHP、ASP.Net MVC技术,都使用MVC模式,当前后端分离越来越常见后,衍生出很多模式,MVVM、MVP等等,如React、Vue等等框架;

    MVC模式是由策略模式 + 观察者模式组合而成,详细如下:

    • Model(模型):
      模型用于获取数据,保存页面的状态;
    • View(视图):
      不同状态下的应用,呈现的视图是不一样的,比如登录页面、个人页面、列表页面;
      接收用户的行为事件,比如点击登录、点击退出、删除等等;
    • Controller(控制器):
      控制器主要是根据应用状态(策略)来切换页面显示;

    M、V、C的依赖场景:
    C根据应用状态,返回不同的V;
    V根据用户的操作产生事件,传递给C;
    C接收事件,做出反应,更新M,返回不同的V给前端;

    代码:

    // 模型(Model)
    interface IUserModelAbserver {
        onLoginStateChanged: (isLogin: boolean) => void,
    }
    
    class UserModel {
        private isLogin: boolean = false
        public constructor(observer: IUserModelAbserver) {
            this.observer = observer
        }
        private observer: IUserModelAbserver
    
        public userLogin() {
            return this.isLogin
        }
    
        public setIsLogin(isLogin: boolean) {
            this.isLogin = isLogin
            this.observer.onLoginStateChanged(isLogin)
        }
    }
    
    // 视图(View)
    enum ViewEvent {
        Login,
        LoginOut
    }
    
    interface IEventHandler {
        onEmitEvent: (event: ViewEvent) => void
    }
    
    abstract class View {
        public handler: IEventHandler
        constructor(handler: IEventHandler) {
            this.handler = handler
        }
        abstract render(): string
    }
    
    class LoginView extends View {
        public onClickLogin() {
            this.handler.onEmitEvent(ViewEvent.Login)
        }
        public render() {
            return '<登录页面的HTML><点击登录></html>'
        }
    }
    
    class UserProfileView extends View {
        public onClickLogout() {
            this.handler.onEmitEvent(ViewEvent.LoginOut)
        }
        public render() {
            return '<用户个人页面的HTML><点击退出></html>'
        }
    }
    
    
    // 控制器(Controller)
    class Controller implements IUserModelAbserver, IEventHandler {
        private model: UserModel
        private view: View
        
        public constructor() {
            this.model = new UserModel(this)
    
            console.log('初始为登录界面')
            this.view = new LoginView(this)
        }
        
        public onLoginStateChanged(isLogin: boolean) {
            console.log('登录状态变更...')
            if (this.model.userLogin()) {
                console.log('用户已登录成功 -> 切换为个人页面')
                this.view = new UserProfileView(this)
            } else {
                console.log('用户退出登录 -> 切换为登录页面')
                this.view = new LoginView(this)
            }
        }
    
        public onEmitEvent(evt: ViewEvent) {
            console.log('用户操作界面,发生事件...')
            if (evt === ViewEvent.Login) {
                console.log('点击登录...')
                this.model.setIsLogin(true)
            } else if (evt === ViewEvent.LoginOut) {
                console.log('点击退出...')
                this.model.setIsLogin(false)
            }
        }
    
        public render() {
            console.log('渲染页面内容...')
            return this.view.render()
        }
    }
    
    // Test
    const controller = new Controller()
    console.log(controller.render())
    
    // 模拟点击登录
    let v: any = controller['view']
    v.onClickLogin()
    console.log(controller.render())
    
    // 模拟退出登录
    v = controller['view']
    v.onClickLogout()
    console.log(controller.render())
    

    输出结果:

    [LOG]: 初始为登录界面 
    [LOG]: 渲染页面内容... 
    [LOG]: <登录页面的HTML><点击登录> 
    [LOG]: 用户操作界面,发生事件... 
    [LOG]: 点击登录... 
    [LOG]: 登录状态变更... 
    [LOG]: 用户已登录成功 -> 切换为个人页面 
    [LOG]: 渲染页面内容... 
    [LOG]: <用户个人页面的HTML><点击退出> 
    [LOG]: 用户操作界面,发生事件... 
    [LOG]: 点击退出... 
    [LOG]: 登录状态变更... 
    [LOG]: 用户退出登录 -> 切换为登录页面 
    [LOG]: 渲染页面内容... 
    [LOG]: <登录页面的HTML><点击登录> 
    

    相关文章

      网友评论

          本文标题:《设计模式》之复合模式(MVC)

          本文链接:https://www.haomeiwen.com/subject/oubuqktx.html