职业IT人-IT人生活圈

 找回密码
 成为会员
搜索
查看: 1863|回复: 9

从银行WebService报文接口系统中,学习敏捷设计

[复制链接]
醉倚西风 发表于 2011-9-4 10:03 | 显示全部楼层 |阅读模式
Preface:

合理的软件架构设计其好处是不言而喻的,系统具有清晰的软件结构,良好的可扩展性,类的职能单一明确,系统的复杂度底。此前的一个实际项目中总结了些关于OO设计的实际应用,主要是围绕‘高内聚及松耦合’,‘开闭原则’的一些应用。

Problem:


目前有一个实际应用放在我们面前,为一个银行现有BI系统开发WebService对外数据接口应用,数据交换方式以预定请求及响应报文来完成,要求可以数据接口系统跨平台使用。即远程客户端发来一种XML数据请求报文,系统按类型执行查询,然后返回XML数据响应报文。

问题也浮出水面,通常此类系统中我们可以想像到,其中一定会有一系列的if else来判断是何种请求报文,然后再执行对应的动作,但我们如果我们这样设计,系统就违反了开放-封闭原则 (OCP,Open-Close Principle),日后的扩展一定需要修改原有代码,而我们期望的是日后添加一种新报文后,只在系统中扩展新的请求、查询及响应对象来实现新需求。

带着问题思考解决办法...

补充:敏捷设计扩展知识手册

拙劣设计的症状:

1.僵化性(Rigidity):设计难以改变。很难对系统进行改动,因为每个改动都会迫使许多对系统其他部分的其他改动。
2.脆弱性(Fragility):设计易于遭到破坏。对系统的改动会导致系统中和改动的地方在概念上无关的许多地方发现问题。3.牢固性(Immobility):设计难以重用。很难解开系统的纠结,使之成为一些可在其他系统中重用的组件。
4.粘滞性(Viscosity):难以做正确的事情。做正确的事情比做错误的事情要困难。
5.不必要的复杂性(Needless Complexity):过分设计。设计中包含有不具有任何直接好处的基础结构。
6.不必要的重复性(Needlsee Repetition):滥用复制/粘贴。设计中包含有重复的结构,而该重复的对象本可以使用单一的抽象进行统一。
7.晦涩性(Opacity):很难阅读、理解。没有很好的表现出意图。


面向对象的设计原则:

1.单一职责原则 (SRP,Single Resposibility Principle)
2.开放-封闭原则 (OCP,Open-Close Principle)
3.Liskov替换原则 (LSP,Liskov Principle)
4.依赖倒置原则 (DIP,Dependicy Independent Priciple)
5.接口隔离原则 (ISP,Interface Seperation Principle)

Solution:

我们初步的想法是,系统接受到一种XML请求后将其转换成请求对象,类似多态的方法,根据不同的请求对象由查询工厂来创建返回不同的查询处理类,再由查询处理类返回填充好的数据响应对象,最后转换成XML响应报文。由此思路,我们完成了UML类图设计,如下:




首先是RemoteQueryService 接口,系统对外的WS服务由此接口完成。

  
/**  
* 类说明: WS远程服务接口<br>  
* 创建时间: 2009-11-6 上午10:07:55<br>  
*   
* @author Seraph<br>  
* @email seraph115@gmail.com<br>  
*   
*/  
public interface RemoteQueryService {   
  
    /**  
     * 功能说明: <br>  
     * 创建者: Seraph<br>  
     * 创建时间: 2009-11-6 上午10:08:09<br>  
     *   
     * @param request  
     * @return  
     */  
    @Profiled(tag = "RemoteQueryService")   
    public String doQuery(String request);   
  
}  

/**
* 类说明: WS远程服务接口<br>
* 创建时间: 2009-11-6 上午10:07:55<br>
*
* @author Seraph<br>
* @email seraph115@gmail.com<br>
*
*/
public interface RemoteQueryService {

        /**
         * 功能说明: <br>
         * 创建者: Seraph<br>
         * 创建时间: 2009-11-6 上午10:08:09<br>
         *
         * @param request
         * @return
         */
        @Profiled(tag = "RemoteQueryService")
        public String doQuery(String request);

}


RemoteQueryServiceImpl 类是此接口的实现,接口方法为接受一种XML请求报文然后返回响应报文。
RegisterContainer 类,在系统初始化时完成不同请求所对应的查询处理类的注册。
QueryFactory 类,根据不同的请求对象返回不同的查询处理类。
ParserRobot 类,负责将XML请求转换为Java请求对象,将Java响应对象转换为XML报文。
QueryProvider 抽象类,是不同种查询处理类的父类。
Request 类,是请求对象的父类。
Response 类,是响应对象的父类。

其中QueryProvider 类,doQuery抽象方法由继承后的子类实现,用来实现不同种报文的查询处理方法,代码为:
  
/**  
* 类说明: <br>  
* 创建时间: 2009-11-6 上午10:21:30<br>  
*   
* @author Seraph<br>  
* @email seraph115@gmail.com<br>  
*   
*/  
@Service  
public abstract class QueryProvider {   
  
    private QueryDaoSupport queryDaoSupport;   
  
    private SqlProvider sqlProvider;   
  
    public abstract Response doQuery(Request request) throws BrwsException;   
  
    public QueryDaoSupport getQueryDaoSupport() {   
        return queryDaoSupport;   
    }   
  
    public void setQueryDaoSupport(QueryDaoSupport queryDaoSupport) {   
        this.queryDaoSupport = queryDaoSupport;   
    }   
  
    public SqlProvider getSqlProvider() {   
        return sqlProvider;   
    }   
  
    public void setSqlProvider(SqlProvider sqlProvider) {   
        this.sqlProvider = sqlProvider;   
    }   
  
}  

/**
* 类说明: <br>
* 创建时间: 2009-11-6 上午10:21:30<br>
*
* @author Seraph<br>
* @email seraph115@gmail.com<br>
*
*/
@Service
public abstract class QueryProvider {

        private QueryDaoSupport queryDaoSupport;

        private SqlProvider sqlProvider;

        public abstract Response doQuery(Request request) throws BrwsException;

        public QueryDaoSupport getQueryDaoSupport() {
                return queryDaoSupport;
        }

        public void setQueryDaoSupport(QueryDaoSupport queryDaoSupport) {
                this.queryDaoSupport = queryDaoSupport;
        }

        public SqlProvider getSqlProvider() {
                return sqlProvider;
        }

        public void setSqlProvider(SqlProvider sqlProvider) {
                this.sqlProvider = sqlProvider;
        }

}  
由UML图中,我们可以看到Request , QueryProvider , Response有许多对应的子类,而每个子类都是一种报文类型,也就是系统所能提供的查询服务。所以目前的架构设计下,日后添加一种新报文将很容易,只需要实现一组 Request, QueryProvide及 Response就可以完成新报文的实现,从而达到了松耦合、可扩展的设计。









fl 发表于 2011-9-4 10:03 | 显示全部楼层
是策略模式的典型使用场景

钰云 发表于 2011-9-4 10:03 | 显示全部楼层
我的想法是使用策略模式,并自己构造classloader对个性化处理的模块进行加载,可以做到server不重启,替换类就可以改变业务处理行为


Jethro 发表于 2011-9-4 10:03 | 显示全部楼层
应该是写个接口吧.......

Jethro 发表于 2011-9-4 10:03 | 显示全部楼层
   另外,敏捷设计``可能我out了...

爱车车 发表于 2011-9-4 10:04 | 显示全部楼层
喜欢这种排版和表达方式~,赞一个~

Jethro 发表于 2011-9-4 10:04 | 显示全部楼层
楼主的精神不错!  

fossil 发表于 2011-9-4 10:04 | 显示全部楼层
UML图需要改进

 楼主| 醉倚西风 发表于 2011-9-4 10:04 | 显示全部楼层
想问一下楼主用的uml设计工具是什么?

无处不在 发表于 2011-9-4 10:04 | 显示全部楼层
学习了。好的架构是成功的开始和关键
您需要登录后才可以回帖 登录 | 成为会员

本版积分规则

QQ|手机版|小黑屋|网站帮助|职业IT人-IT人生活圈 ( 粤ICP备12053935号-1 )|网站地图
本站文章版权归原发布者及原出处所有。内容为作者个人观点,并不代表本站赞同其观点和对其真实性负责,本站只提供参考并不构成任何投资及应用建议。本站是信息平台,网站上部分文章为转载,并不用于任何商业目的,我们已经尽可能的对作者和来源进行了通告,但是能力有限或疏忽造成漏登,请及时联系我们,我们将根据著作权人的要求立即更正或者删除有关内容。

GMT+8, 2024-5-1 01:56 , Processed in 0.142219 second(s), 20 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表