惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
罗磊的独立博客
M
MIT News - Artificial intelligence
G
Google Developers Blog
V
V2EX
D
Docker
博客园_首页
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
WordPress大学
WordPress大学
T
Tailwind CSS Blog
博客园 - 司徒正美
J
Java Code Geeks
L
LangChain Blog
博客园 - 三生石上(FineUI控件)
B
Blog RSS Feed
博客园 - 【当耐特】
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
大猫的无限游戏
大猫的无限游戏
P
Proofpoint News Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - Franky

博客园 - Birdshover

express-partials与express4.x不兼容问题 该省代码的地方要省,反之亦然。 dell笔记本的Broadcom 802.11b/g 无线网卡ubuntu 9.10下安装 四步完成跨平台调用——thrift的开发应用 facebookde 的 NoSQL数据库cassandra的配置与调用(java&&c#) VirtualBox 虚拟机 Debian系统上安装Cassandra步骤及遇到的问题 大道化简,重构的艺术 读自己的书,走自己的路 厨师炒菜与网站反爬虫问题 jre6的webservice使用Php类库nusoap调用的问题 - Birdshover - 博客园 mysql master/slave 使用感受 java开发守护进程 实现高效易用的java操作mysql包装 部分NLuke版本源码更新(2009-11-1) 单件模式的陷阱 一个不必要的设计 网站、数据库的衍变之路(六) 网站、数据库的衍变之路(五) ASP.NET Forms验证的安全性问题研究——为什么加密代码需要配置为服务
选择结构(if..else..,switch,try..catch..)的拆分
Birdshover · 2010-12-02 · via 博客园 - Birdshover

编程中经常遇到很多条件,以及条件套条件的情况,以至于一个方法会写得非常地长。有多种方法可以规避这个问题。比如反射,策略模式,表驱动等等。先抛开这些方法不讲,从根本需求来探索这个过程。

一个switch结构可能是这样:

swicth(case)

  case 1:

    //do1

    break;

  case 2:

    //do2

    break;

  .....

这里注释的do部分代码可能会是很多很多行,以及嵌套switch,if结构。

进一步,这个模型演化成

swicth(case)

  case 1:

    do1();

    break;

  case 2:

    do2();

    break;

  .....

do1(){}

do2(){}

也就是将里面的代码模块化。这个方法有效的减小了一个方法的代码长度。实际上这就是一个映射关系的调用。建立映射关系,用Hash结构和delegate就可以避免使用switch了。

delegate void funtionptr();

Dictionary<int, funtionptr> dict = new Dictionary<int, funtionptr>();

dict.Add(1,do1);

dict.Add(2,do2);

int parm = 0;

if(dict.ContainKey(parm)){

  dict[parm].Invoke();

do1(){}

do2(){}

这个方法实际上就是表驱动,因为C#中一般不用指针,因此用delegate代替了指针的作用。而java中既没有指针也没有delegate怎么办呢?那就用接口模拟指针。

(这里就用C#的语法了,不使用JAVA了)

interface FactionFace{

  void do();

class FactionFaceImpl1 : FactionFace{

  public void do(){}

class FactionFaceImpl2 : FactionFace{

  public void do(){}

Dictionary<int, FactionFace> dict = new Dictionary<int, FactionFace>();

dict.Add(1,new FactionFaceImpl1());

dict.Add(2,new FactionFaceImpl2());

int parm = 0;

if(dict.ContainKey(parm)){

  dict[parm].do();

可以看出,实际上,上面的代码就是策略模式的简单实现了。(OH~~原理策略模式这么就来的~~)

可以看出,这里实际上是依靠一个字典来维护条件和调用的关系的。那如果没有这个字典来维护怎么办呢?代码再次演化:

interface FactionFace{

  void do();

class FactionFaceImpl1 : FactionFace{

  public void do(){}

class FactionFaceImpl2 : FactionFace{

  public void do(){}

string parm = "FactionFaceImpl2";

FactionFace ff = Type.GetType(parm) as FactionFace;

ff.do();

OH~~这就是简单的反射了。再复杂一些就可以搞成工厂模式,插件模式了。

可以看出,用字典来维护映射关系就可以避免使用反射。(这个是不是一般规律,贫道没本事证明,起码这里是适应的。)

再来看try...catch...

delegate void forException(Exception ex);

public void forAException(Exception ex) {Console.WriteLine("AException");}
public void forAAException(Exception ex) {Console.WriteLine("AAException");}
public void forBException(Exception ex) {Console.WriteLine("BException");}

public void test() {

  Dictionary<int, forException> dict = new Dictionary<int, forException>();

  dict.Add(0, forAException);

  dict.Add(1, forAException);

  dict.Add(11, forAAException);

  dict.Add(2, forBException);

  try {

    throw new AAException();

  } catch (Exception ex) 

  {

    if (ex is OException) {

      OException eex = ex as OException;

      if (dict.ContainsKey(eex.Index)) {

         dict[eex.Index].Invoke(ex);

      }

    }

  }

}

public class OException : Exception {public virtual int Index { get { return 0; } }}
public class AException : OException {public override int Index {get {return 1;}}}
public class AAException : AException {public override int Index {get {return 11;}}}
public class BException : OException {public override int Index {get {return 2;}}

这里为啥要有个Index属性呢?其实就是建立个对应的关系,而不是靠名字去维护。去掉这个属性,直接使用ex.GeType()然后获取名字类名也一样可以建立对应关系。