• 什么是接口(中级篇)——接口在设计模式中的使用(一)


    设计模式——一个会让很多人觉得高大上的名词。

    实际上,设计模式并没有什么高深的知识在里面,它只是一种思想,使用这种思想,可以使得你的系统更容易被更新、维护,尽可能得避免了所谓的”动一发触全身“的被动状态。

    我们把上面的话反过来看一下,就变成另一个意思了:

    我们尽可能得使得系统变得容易更新、容易维护,我们使用各种办法使得”动一发触全身“的被动状态发生率降至最低的思路,就是设计模式的原出发点了。

     

    关于设计模式的文章,网络上也是大把大把的,一般都会按照它们总结出来的各种模式一一介绍,比如用一篇文章介绍一下工厂模式(公认最简单的模式)。

    但是我不认为设计模式是真有着明显的这个或者那个模式,而是一种思想,只要使用到了,就是好的。

    我将顺着”什么是接口”,这系列的教学,带大家正式进入“设计模式”的教学篇,在这里,我们不是生硬得将设计模式拆开后一个一个讲解。而是将分析的思路慢慢溶入每一行代码中,自然而然的形成了各种设计模式。

     

    首先,我们来看看这个例子:

    对于一个做过几个项目的人来说,让他们去完成任何平台(窗体、网页等)上的登录行为,那是太容易不过的事了。

    他们的思路肯定是这样的:

    1、一个方法:接受参数 用户名,密码

    2、拿这两个参数拼一个SQL语句

    3、判断是否有查询结果

    3-Y、记录下用户ID(以备后用),再加上一些其它操作,跳转窗体、页面,登录完成

    3-N、提示用户”用户名或密码错误“

    “很好,这样就完成了,太简单不过了” —— by 无名的程序员

     

    唔,确实,从功能上来说,确实完成的非常好

    然后我们来假设一些可能会遇到的情况:

     

    1、要求单点登录,即一个用户不可以登录两次

    “这好办,在判断登录成功后,再加一堆代码,判该这个用户ID是否在线,如果不在线才可以登录;如果在线提醒他” —— by 无名的程序员

    唔,很轻松地解决了这个问题,很好。我们继续

     

    2、你的上司希望这个单点登录是个可选的逻辑

    "这依然简单,在配置文件写一个开关,在(1)添加的代码前加判断,小轻松~~" —— by 无名的程序员

    唔,解决的很漂亮,以后只要改改配置文件,什么都不是问题了

     

    3、项目越做越大,不光有窗体,还有网站,还有手机,我们不能一个一个写登录了,需要统一一个WebService控制所有程序

    "唔,这次我学乖了,还是先做一个配置开关吧,顺便把WebService的URL也存进去,表示是否使用统一登录机制,然后利用分支来进行不同的登录流程" —— by 有长进的无名程序员

    不得不说,变厉害了。

     

    4、由于重大版本的更新,表结构变了……

    5、由于重大版本的更新,WebService协议变了——

    6、登录流程出现了BUG

    "哎呀,登录流程有这么多分支,到底哪出BUG了" —— by 抓头的无名程序员

     

    随着产品的不断提升,需求在变,功能也在变,堆着一堆配置项和一堆switch代码,时间久了,自己都不一定能管理好这些思路,更不要说,这只是登录。

    现在我们设想一下:

    我们现在站在一个豪宅的大门口,我们想进去 —— 登录

    我们只需要给门卫看一下脸、报一下名字、出示一下门卡 —— 用户名 + 密码

    门卫去后面干了些你不知道的事情 —— 登录流程

    门卫告诉你可以进、或是不可以进 —— 登录结果

     

    有没有发现一个很关键的事情? —— 登录流程我们不关心

    对我们手上的这段代码来说,最关心的是如果登录成功干什么,如果登录失败干什么。

    至于如何验证,按理说,不是这时候考虑的,应该有一个专门的"东西"负责这件事,至于这个东西怎么完成的,和我没关系。

    这个概念,恰恰好与接口想吻合 —— 一个只提供了方法签名、属性、事件,但不去实现其功能的最抽象的类型

    public interface ILoginChecker
    {
        bool Login(string loginName,string password);
    }

    在你的代码中只需要声明一个ILoginChecker成员,并通过构造函数来决定它的具体类型,在程序中直接使用它即可。

    public class LoginWindow : Form
    {
        private ILoginChecker loginChecker;
    
        public LoginWindow(ILoginChecker chcker)
        {
            this.loginChecker = chcker;
        }
    
        void LoginButton_Click(object sender, EventArgs e)
        {
            string loginName = null, password = null;
            //从控件上取值
            //判断空值
            //等一切OK时
            if (this.loginChecker.Login(loginName, password))
            {
                //登录成功
            }
            else
            {
                //登录失败
            }
        }
    }

    我们来总结一下思路,把不关心的、可变的、可调整、可维护的内容,先不去实现,写成一个接口,直接使用这个接口上的方法,并把接口的填充交给构造函数(这一步不是必须)

    我们把这个思路叫作 —— "控制反转",简称IOC

     

    控制反转,是在大型项目中最常见存在的一种模式。Java中最有名的框架Spring其核心就是一个控制反转容器。

    本次介绍的只是控制反转中最核心的思想,示例代码尚不能作为一个优秀的控制反转示例。

     

    文章为作者原创,转载请注明出处,谢谢 http://www.cnblogs.com/ShimizuShiori/p/4923427.html

  • 相关阅读:
    10天掌握webpack 4.0 Html 插件
    10天掌握webpack 4.0 服务篇
    spring boot 国际化信息
    Java 编程下使用 Class.forName() 加载类
    Java 编程下正则表达式判断字符串是否包含中文
    Adb connection Error:远程主机强迫关闭了一个现有的连接 解决方法
    Java 编程下简介 Class 与类加载
    通过htaccess文件配置多个一级域名指向根目录的子文件夹
    apache httpd.conf
    composer安装laravel框架时未生成Vendor解决办法
  • 原文地址:https://www.cnblogs.com/ShimizuShiori/p/4923427.html
Copyright © 2020-2023  润新知