我的asp.net经验之谈

asp.net技术相关

博客园 首页 管理
  100 Posts :: 0 Stories :: 1283 Comments :: 44 Trackbacks
最近项目里遇到了一个问题,为了解决这个问题“动用了”继承、多态还有工厂模式和反射,但是还是没有OO的感觉。呵呵。

先说一下具体情况:
1、使用短信猫来接收短信。简单的说,短信猫收到短信后会往指定的表里面填写数据。
2、接收到短信,然后根据短信前面的“标志”调用不同的方式来处理。
3、发送确认信息或者是错误提示。
4、想做成一个“通用”的模块,不管是什么项目,都可以使用这个程序来处理接收短信的问题。当然具体的处理方式要能很方便的修改或者扩充。


我的实现方式:
1、定义一个基类,用来处理接收到的短信。
2、由于每一种短信的处理方式都不同,所以需要好多的不同的子类。每一个子类来处理一种短信。
3、调用的时候 如果用 case 的方式的话,每增加一总短信都要修改case 。很烦!而且当应用在一个项目里的时候,case 就得推倒重来,烦!
     最后使用了反射。
4、建立了三个项目,一个是winform的用来检查表里面是否有新的短信,叫做A ;一个是处理短信的项目,叫做B;最后一个就是具体的项目了。

==============
说明:
 具体的项目指的是,可能是A公司的OA,可能是B公司的CRM,也可能是C公司的ERP。
 这里说的是分“项目”,而不是分层。
 处理短信的项目要根据不同的公司的不同的需求来编写,写完了之后编译成DLL,交由 A 来调用。
==============

5、其中 A 是通用的,写好了基本不变。B编译成dll,好让A来调用。
6、A 调用处理短信的类。由于使用了反射,可以“动态”的指定dll名称和类名。这样就很灵活了,处理短消息的方式有变化的话,只需要更新dll就可以了。
  换成新的项目的时候,换成新的dll就可以了。这样A就不用改了。


现在基本功能是实现了,但是这样就OO了吗?还是没有OO感觉。

感觉还是在用面向过程的思路来写程序,一个子类里面只有一个函数,和面成过程有什么区别呢?

您可能要问了,那我为什么还要用多态呢?其实很简单,这样就可以使用“反射”了,这样我就不用写case了,可以让A不必随不同的项目而修改了。

说白了就是想当变化的时候少改点代码。

正在看面向对象、设计模式了什么的,把自己的想法、做法写出来,请大家批批。


ps:这里好象用“观察者”更好一点,A就是一个发布者,B是一个订阅者,只是我不知道如何让B来订阅A。
也许根本就不适合吧,毕竟有新的短信了,只有一种处理方法是对应的,其他的都不是。

代码补充:

namespace HBS.SMSReceive
{
    
/// <summary>
    
/// 接收短信。基类
    
/// </summary>

    public class MessageReceive
    
{
        
public DataAccessLayer dal ;
        
        
处理短信的函数

        
把短信移动到历史记录里面
    }


    
子类1:处理没有标志的短信

    
子类2:MessageOperation01 第一种短信的回执
}



然后就是A里面的调用的代码

//获取短信内容,放在 DataTable dt 里面
//然后遍历 dt

Assembly.Load("SMS").CreateInstance("SMS.短信" + 短信开头的编号)

代码补充:
处理接收到的短信


大体就是这样了。


反射还是在看了伍迷的小菜系列才会用的,再此表示感谢。
posted on 2008-01-15 21:24 金色海洋(jyk) 阅读(2558) 评论(40)  编辑 收藏 所属分类: 面向过程与面向对象

评论

我觉得吧
不是用上了继承,多态,反射就是面向对象
反之亦然
  回复  引用    

#2楼  2008-01-15 21:58 李华星      
我觉得用观察者模式好象有点牵强, 因为观察者模式表示发布者的状态变化引起订阅者的变化, 你可以用职责链模式,试试,也许能达到你的要求
  回复  引用  查看    

#3楼  2008-01-15 22:44 涛涛2008      
在项目中多用一些设计模式,多思考,用多了就会了!
  回复  引用  查看    

#4楼  2008-01-15 23:49 e2mars [未注册用户]
Simple Factory,感觉有点像你要的效果,虽然不是GOF的DP
  回复  引用    

关于消除代码中的case语句,你可以找本讲代码重构的书,那里面一般都会讲到使用多态来替代case语句的重构过程.感觉这个可能是你期望的OO方法.
  回复  引用    

#6楼  2008-01-16 01:54 OMG [未注册用户]
OO只是方法而不是目的。
  回复  引用    

#7楼 [楼主] 2008-01-16 07:08 金色海洋(jyk)      
其实我只是想完成任务,至于用到了什么,符合什么模式我都是不关心的。

只是完成了任务之后,发现这就是传说中的OO吗?OO是不是这样子的呢?

我不敢说我这么写代码就是OO了。

不管怎么说,至少目前是实现了目标。
  回复  引用  查看    

#8楼  2008-01-16 08:23 阿武      
我觉得用简单工厂即可, 你的反射实现方式限制了"接收短信"的具体类名称必须是"短信+编号", 这是很不合理的, 而且这样的命名方式也有问题, 客户端即使用者没办法通过类名称来判断它表示的意义
  回复  引用  查看    

#9楼  2008-01-16 08:43 江水滔滔      
分层的目的
1:程序员可以分工协作。可以由设计人员定义好。开发人员具体实现
2:可以分布部署,增加服务器负载功能

分层
不是单单就是DLL应用过来
那时候我在苏州,一直不懂,开发的时候明明就布就可以做到。开发的时候非要一层一层的写。
当时部署的时候,前端->調用Remoting,!||防火强->后面的

前端根本就没有办法直接访问到后端,根本没有办法调用。

至于OO吗?我也不懂。但是最近我有点迷惑了
就是我现在开发单子,所有的单子就基本一样。只是自己大体的表不一样

现在的做法全部是COPY,万一,哪天我基本数据库要改,你说我要改多少呢?
其实可能项目要不断的变化,不断的升级才可能体会到OO的作用

--------------------------------------------------------------
还有我罗嗦了,
举个列子:人事系统 :是A组开发的。
资产系统: B组开发
市场系统 : C组开发

现在我出来一个新系统

这里面所有数据库都是独立的,不可能公开给每个组。
这个时候你怎么办呢?
A:提供业务接口
B:提供业务接口
C: 提供业务接口
新负责:调用。我调用的,什么都不要知道。我只看名字,具体做了什么,我都不要关心。

我罗嗦了,最近我也在迷惑
  回复  引用  查看    

#10楼  2008-01-16 09:01 henry      
能否提高开发效率?能否提供代码的可以维护性?如果能你会爽不?
不过方法是因人已异的,说不定以后维护这代码的兄弟会说什么狗屎代码哇,用一大堆我搞不懂的代码来完成这样的功能....结论就是你这样写搞到他很不爽呵呵
  回复  引用  查看    

#11楼  2008-01-16 09:20 Anytao      
型多了,感觉就来了,OO是不断重构的过程,一次到位建立在经验之上。其实将一个方法实现在不同的类中,类的功能划分,本身就体现着OO。
  回复  引用  查看    

#12楼  2008-01-16 09:23 我是蚂蚁      
首先要理解,然后去用,然后再理解,然后再重构....

照虎画猫也不容易
  回复  引用  查看    

#13楼  2008-01-16 09:42 xiao_p      
oo 是啥感觉? 难道用了oo你能精神百倍? :-)
  回复  引用  查看    

#14楼  2008-01-16 09:51 李洪超      
你自己没有发现吗?你已经应用了一种设计模式了,策略模式(Strategy),而且应用的非常好,可以在配置文件中指定调用哪个dll,程序中就来调用这个dll,来执行一系列的操作,就更方便了.
不要为了OO而OO,而是为了解决问题,你现在通过这种方法解决了问题,那就可以了,我比较欣赏的一句话是Refactoring to Pattern.

  回复  引用  查看    

#15楼  2008-01-16 10:04 Sapphire [未注册用户]
OO是種思想了,程序是由個種職責的對象團結協作來完成功能...這樣才OO..當程序沒有這樣的[對象團結協作]的感覺時,就沒有OO的感覺了
  回复  引用    

#16楼  2008-01-16 10:23 球球      
4、建立了三个项目,一个是winform的用来检查表里面是否有新的短信,叫做A ;一个是处理短信的项目,叫做B;最后一个就是具体的项目了。
----------------------
这句话没太看明白,还有不具体的项目吗?
我倒是感觉没必要为了OO而OO,有的工程用OO还不如过程来的方便。
你感觉不OO,情况可能很多,最主要的是,你的工程分了多少层,一般来说,小型的三层的程序至少有DAL,BLL,UI,Model四个工程,伍迷那个我记得好像因为都用基本类型,所以Model忽略掉了,Model要被其他三个引用,DAL被BLL引用,BLL被UI引用,在做到这些以后才能再考虑设计模式之类的东西。
  回复  引用  查看    

#17楼  2008-01-16 10:52 G yc {Son of VB}      
没有太明白

我刚刚想到的,用那种工厂方法一类不可以吗(肯能说的不准确)

比如做一个处理类,用来处理短信接收等。然后他接受一个Rule数组(在内部)。

在遇到数据后,将会按照Rule中的指定方法进行调用。

Rule可以设计成类,也可以是接口, 并定义一个实现方法。上面那个类会调用这个方法。

之后,把这一个Rule和一个条件 都放到处理类 里面。
内部循环检查,条件,包括没有找到的时候,添加的时候检查是否有重复条件等。
——————————
大概就是这个样子吧。不着调准不准确~~
  回复  引用  查看    

#18楼  2008-01-16 12:29 江大鱼      
Assembly.Load("SMS")...

有这个必要么?OO不是目的, 简单,迅速,高质量的解决问题才使你的目的
  回复  引用  查看    

#19楼 [楼主] 2008-01-16 20:50 金色海洋(jyk)      
感谢大家的回复。白天又去客户那里了。没有及时回复。


  回复  引用  查看    

#20楼  2008-01-17 09:44 m j [未注册用户]
像 @李洪超 所说,可以改进一下,用工厂来产生MessageReceive对象

#region 处理接收到的短信
private void monitorInSMS()
{
...
foreach (DataRow dr in dt.Rows)
{
...
msgRecv = MessageReceiveFactory.GetMessageReceive("HBS.SMSReceive.MessageOperation" + msg[0].Trim());
...
}
}

MessageReceiveFactory做的事就是从配置文件里面按规则取得类名,反射生成对象,并缓存起来

配置文件就像这样:
<MessageReceive name="规则A" type="类A"/>

这样做之后,
1、更灵活,改规则或者添加规则只需要改改配置,最多再加新的DLL就可以了
2、大大减少反射的性能消耗,不需要每次调用都重新反射生成一次了
  回复  引用    

sorry,你的代码确实没有体现OO思想。应该面向接口编程,而不是面向实现。
  回复  引用    

#22楼 [楼主] 2008-01-17 11:40 金色海洋(jyk)      
@m j
请问:
MessageReceiveFactory.GetMessageReceive ()

是怎么实现的(就是内部代码),不用case 可以吗?


@Michael.zy
接口是一个广义的感念,不仅仅局限于 interface 。基类也可以看成是一种“接口”。


  回复  引用  查看    

#23楼  2008-01-17 13:03 亚历山大同志      
莫要为了OO而去OO,没意义
  回复  引用  查看    

#24楼  2008-01-17 13:21 球球      
仔细看了看,果然DAL和BLL是混合在一起的,不过简单的工程这样做也可以,只是不太符合OO的思想,没有实体类,都用基本类型,看起来眼晕点,好在东西少,还可以接受,当短信无法识别好像throw个error更好些,但目前看为了省事也不一定非加不可,应该是用了一个简单工厂,这里带有OO的性质,但也谈不上模式,至于反射,最少我不认为它和OO有什么关系,我感觉那东西就是一个很实用的技巧而已。所以这个程序LZ的感觉没错,确实和OO挨不上多少。但这个工程值不值得用OO真是个问题。
另,伍迷那个文章里用的是策略模式,但感觉有点牵强,那个例子用装饰应该会舒服很多,个人意见。
  回复  引用  查看    

#25楼  2008-01-17 14:43 m j [未注册用户]
public class MessageReceiveFactory
{
Dictionary<string, MessageReceive> dic = new Dictionary<string, MessageReceive>();

public MessageReceiveFactory()
{
// 获取配置信息,这里假设存在AppSettings里
NameValueCollection config = ConfigurationManager.AppSettings;
foreach (string key in config.Keys)
{
string value = config[key];
MessageReceive msgRec = ... // 反射
dic.Add(key, msgRec);
}
}

public MessageReceive GetMessageReceive (string keywords)
{
if(!dic.contains(keywords))
throw new Exception();
return dic[keywords];
}
}

类似这样,当然这些MessageReceive还可以在第一次调用时才生成了
  回复  引用    

#26楼 [楼主] 2008-01-17 20:45 金色海洋(jyk)      
@亚历山大同志
没有为了OO而OO,只是完成了任务后写一下感觉。
看看大家的批评。


@球球
因为是短信,throw个error的话,发短信的人是看不到的。
所以我用 public class MessageOperationOther:MessageReceive 这个子类来给法短信的人一个回复信息。

还在用vs2003,不支持范型的。


  回复  引用  查看