SmartPublisher设计之旅 — 软件设计无需后悔莫及

新的需求

在《SmartPublisher设计之旅 - 让理想在仇恨中茁壮成长》一文中提到:SmartPublisher作为一种网络营销工具,对软件所有者来说,希望能给公司带来新的利润,要求软件需要增加以下功能:


1)对企业会员发布信息进行收费,并不同会员类型有不同的按照收费标准。
普通型会员:企业注册审核通过后即为普通会员,普通型会员发布1条信息按照1分钱/有效站点标准收取。
商务型会员:普通型会员消费满10000元即成为商务型会员,商务型会员发布1条信息按照0.5分钱/有效站点标准收取。
豪华型会员:商务型会员消费满100000元即成为豪华型会员。商务型会员发布1条信息按照0.1分钱/有效站点标准收取。


2)企业会员缴费有三种方式:手机缴费,购买冲值卡,银行转帐。

SmartPublisher并没有设计完成,需要增加以上功能并非难事情。然而,真正困难的是软件设计已经完成甚至整个软件已经进入维护阶段,需要在不改变原来设计的前提下增加功能就必须三思而后行。由于前期设计中多处采用接口,所以很明显不能修改接口,因为这样一来会直接导致继承该接口的所有类都必须更改。接下来,看看在不改变原来设计的前提下能否顺利增加软件功能。似乎有点故弄玄虚的感觉,哈哈。

数据库结构的变化

根据以上需求,需要增加两个数据表:企业会员充值记录表和消费记录表,当然还增加了会员类型字段(MemberType)。根据《SmartPublisher设计之旅 - 让梦想成为理想》文中的数据表设计规律,充值表和消费表与企业会员之间关系均为一对多关系,当然还需要在企业会员表中增加会员型号字段。修改后的数据表关系图如下:

r_PublisherDB2.JPG

数据访问层设计的变化

由于增加增加了两个数据对象,所有在数据访问层中需要增加以下类。由于在前面设计时,已经提供了一个数据表操作的统一接口,可以很方便的设计两个对象的实体类和访问类。这样并没有对原有的代码进行修改。

ContractedBlock.gif ExpandedBlockStart.gif EnterpriseFee实体类
None.gifusing System;
None.gif
None.gif
namespace PublisherLib.DataAccessLayer
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class EnterpriseFee
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private string _ID;
InBlock.gif        
private string _EnterpriseID;
InBlock.gif        
private double _FeeAccount;
InBlock.gif        
private DateTime _FeeTime;
InBlock.gif
InBlock.gif        
public string ID
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._ID; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._ID = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public string EnterpriseID
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._EnterpriseID; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._EnterpriseID = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public double FeeAccount
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._FeeAccount; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._FeeAccount = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public DateTime FeeTime
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._FeeTime; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._FeeTime = value; }
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

ContractedBlock.gif ExpandedBlockStart.gif EnterpriseFeeDAL
None.gifusing System;
None.gif
using System.Data;
None.gif
using System.Text;
None.gif
using PublisherLib.DbAccess;
None.gif
None.gif
namespace PublisherLib.DataAccessLayer
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class EnterpriseFeeDAL:ITableOperator<EnterpriseFee>
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
ITableOperator 成员#region ITableOperator<EnterpriseFee> 成员
InBlock.gif
InBlock.gif        
public bool Add(EnterpriseFee model)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool Update(EnterpriseFee model)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool Delete(string ID)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int GetCount(string strWhere)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public EnterpriseFee GetModel(string ID)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public DataSet GetList(string strWhere)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

ContractedBlock.gif ExpandedBlockStart.gif EnterpriseCharge实体类
None.gifusing System;
None.gif
None.gif
namespace PublisherLib.DataAccessLayer
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class EnterpriseCharge
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private string _ID;
InBlock.gif        
private string _EnterpriseID;
InBlock.gif        
private double _ChargeAccount;
InBlock.gif        
private DateTime _ChargeTime;
InBlock.gif
InBlock.gif        
public string ID
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._ID; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._ID = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public string EnterpriseID
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._EnterpriseID; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._EnterpriseID = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public double ChargeAccount
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._ChargeAccount; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._ChargeAccount = value; }
ExpandedSubBlockEnd.gif        }

InBlock.gif        
public DateTime ChargeTime
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif            
get dot.gifreturn this._ChargeTime; }
ExpandedSubBlockStart.gifContractedSubBlock.gif            
set dot.gifthis._ChargeTime = value; }
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

ContractedBlock.gif ExpandedBlockStart.gif EnterpriseChargeDAL
None.gifusing System;
None.gif
using System.Data;
None.gif
using System.Text;
None.gif
using PublisherLib.DbAccess;
None.gif
None.gif
namespace PublisherLib.DataAccessLayer
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class EnterpriseChargeDAL:ITableOperator<EnterpriseCharge>
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
ITableOperator 成员#region ITableOperator<EnterpriseCharge> 成员
InBlock.gif
InBlock.gif        
public bool Add(EnterpriseCharge model)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool Update(EnterpriseCharge model)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public bool Delete(string ID)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int GetCount(string strWhere)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public EnterpriseCharge GetModel(string ID)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public DataSet GetList(string strWhere)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

业务逻辑层设计改进

经过对新需求的分析,我们对业务逻辑层进行改进。对企业会员管理来说,再提供以下功能:
1)获取企业会员类型
2)修改会员类型

3)企业会员充值
4) 获取企业充值明细
5)获取企业充值总额

6)保存消费记录
7)获取企业消费明细
8)获取企业消费总额

起初我们已经定义了会员管理的接口IEnterpriseBLL,但是又不能在这个接口上增加上述方法。在23种设计模式中,我们想到适配器模式(Adapter)可以很方便的把IEnterpriseBLL接口适配成具有会员管理功能的新接口。我们只需要再定义一个会员管理的接口IEnterpriseMemberBLL,由新的业务层访问类EnterpriseMemberBLL,并且继承IEnterpriseMemberBLL和原来的业务层访问类EnterpriseBLL。这样一来,UI表示层只需要与EnterpriseMemberBLL发生关系就可以了。

using  System;
using  System.Text;
using  System.Data;
using  PublisherLib.DataAccessLayer;

namespace  PublisherLib.BusinessLogicLayer
{
    
public   interface  IEnterpriseMemberBLL
    {
        
string  GetMemberType( string  enterpriseID);
        
bool  UpdateMemberType( string  enterpriseID,  string  memberType);

        
bool  AddEnterpriseFee( string  enterpriseID,  double  feeAmount);
        DataSet QueryEnterpriseFeeList(
string  strCondition);
        
double  GetEnterpriseFeeSum( string  enterpriseID);

        
bool  AddEnterpriseCharge( string  enterpriseID,  double  chargeAmount);
        DataSet QueryEnterpriseChargeList(
string  strCondition);
        
double  GetEnterpriseChargeSum( string  enterpriseID);
    }
}

using  System;
using  System.Text;
using  System.Data;
using  PublisherLib.DataAccessLayer;

namespace  PublisherLib.BusinessLogicLayer
{
    
public   class  EnterpriseMemberBLL:EnterpriseBLL,IEnterpriseMemberBLL
    {
        
#region  IEnterpriseMemberBLL 成员

        
public   string  GetMemberType( string  enterpriseID)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
public   bool  UpdateMemberType( string  enterpriseID,  string  memberType)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
public   bool  AddEnterpriseFee( string  enterpriseID,  double  feeAmount)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
public  DataSet QueryEnterpriseFeeList( string  strCondition)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
public   double  GetEnterpriseFeeSum( string  enterpriseID)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
public   bool  AddEnterpriseCharge( string  enterpriseID,  double  chargeAmount)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
public  DataSet QueryEnterpriseChargeList( string  strCondition)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
public   double  GetEnterpriseChargeSum( string  enterpriseID)
        {
            
throw   new  Exception( " The method or operation is not implemented. " );
        }

        
#endregion
    }
}

发布引擎设计改进

首先我们在前期设计中,发布引擎只是提供信息发布的功能,现在需要根据不同的会员类型进行收费。在收费用之前,我们定义对企业会员操作的接口,以提供引擎调用。
using  System;

namespace  PublisherEngine.Engine
{
    
public   interface  IMember
    {
        
int  GetCurrentSucceedNumber( string  dataID, string  dataType); // 获取指定信息的成功发布数量
         string  GetMemberType( string  enterpriseID); // 获取企业会员类型
         double  GetChargeSum( string  enterpriseID); // 获取企业收费总额
         void  UpdateMemberType( string  enterpriseID,  string  memberType); // 修改企业会员类型
    }
}

ContractedBlock.gif ExpandedBlockStart.gif EnterpriseMember具体类
None.gifEnterpriseMember
None.gif
using System;
None.gif
None.gif
namespace PublisherEngine.Engine
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class EnterpriseMember:IMember
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        IMember 成员
IMember 成员#region IMember 成员
InBlock.gif
InBlock.gif        
public int GetCurrentSucceedNumber(string dataID, string dataType)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public string GetMemberType(string enterpriseID)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public double GetChargeSum(string enterpriseID)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void UpdateMemberType(string enterpriseID, string memberType)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

不同会员类型本质上区别在于不同的收费算法,很明显我们可以采用 策略模式(Strategy)来实现。首先我们定义一个收费接口。
using  System;

namespace  PublisherEngine.Engine
{
    
public   interface  ICharge
    {
        
double  _Rate {  get ; set ;} // 价格,如0.01\0.005\0.001
         int  ScceedNumber {  get ; set ;} // 成功发送的信息条数
         void  Charge();
    }
}
然后定义三种会员类型具体实现类。
ContractedBlock.gif ExpandedBlockStart.gif CommonCharge普通型会员
None.gifusing System;
None.gif
None.gif
namespace PublisherEngine.Engine
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class CommonCharge : ICharge
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        ICharge 成员
ICharge 成员#region ICharge 成员
InBlock.gif
InBlock.gif        
public double _Rate
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int ScceedNumber
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void Charge()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

ContractedBlock.gif ExpandedBlockStart.gif BusinessCharge商务型会员
None.gifusing System;
None.gif
None.gif
namespace PublisherEngine.Engine
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class BusinessCharge:ICharge
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        ICharge 成员
ICharge 成员#region ICharge 成员
InBlock.gif
InBlock.gif        
public double _Rate
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int ScceedNumber
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void Charge()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

ContractedBlock.gif ExpandedBlockStart.gif LuxuryCharge豪华会员
None.gif
None.gif
using System;
None.gif
None.gif
namespace PublisherEngine.Engine
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public class LuxuryCharge:ICharge
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ContractedSubBlock.gifExpandedSubBlockStart.gif        
ICharge 成员#region ICharge 成员
InBlock.gif
InBlock.gif        
public double _Rate
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public int ScceedNumber
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

InBlock.gif            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void Charge()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
throw new Exception("The method or operation is not implemented.");
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

我们约定,普通型会员标识为Common,商务型会员标识为Business,豪华型会员标识为Luxury。可以通过会员ID获取会员类型字符串,然后根据字符串的值来决定调用哪个收费具体类。我们可以定义配置文件( MemberType.xml)配置不同会员类型收费价格及实例化类名。
<? xml version = " 1.0 "  encoding = " utf-8 "   ?>
< root >
    
< Common >
        
< Rate > 0.01 </ Rate >
        
< ClassName > PublisherEngine.Engine.CommonMember </ ClassName >
    
</ Common >
    
< Business >
        
< Rate > 0.005 </ Rate >
        
< ClassName > PublisherEngine.Engine.BusinessMember </ ClassName >
    
</ Business >
    
< Luxury >
        
< Rate > 0.001 </ Rate >
        
< ClassName > PublisherEngine.Engine.LuxuryMember </ ClassName >
    
</ Luxury >
</ root >  
然后在策略环境类(Cash)中获取企业类型,通过 依赖注入(Dependency Injection)实例化具体收费类,并根据条件修改企业会员类型。
using  System;
using  System.Xml;
using  System.Reflection;

namespace  PublisherEngine.Engine
{
    
public   class  Cash
    {
        
private  ICharge _charge;
        
private  IMember _member;
        
private   string  _EnterpriseID;
        
private   string  _DataID;
        
private   string  _DataType;
        
public  Cash( string  enterpriseID, string  dataID, string  dataType)
        {
            _EnterpriseID 
=  enterpriseID;
            _DataID 
=  dataID;
            _DataType 
=  dataType;
        }
        
public   void  Charge()
        {
            _member 
=   new  EnterpriseMember();
            
string  membertype  =  _member.GetMemberType(_EnterpriseID); // 获取会员类型

            XmlDocument doc 
=   new  XmlDocument();
            doc.Load(
" MemberType.xml " );
            XmlNode root 
=  doc.DocumentElement;

            _charge 
=  (ICharge)Assembly.GetExecutingAssembly().CreateInstance(root.SelectSingleNode( " /Common/ClassName " ).Value);
            _charge.Rate 
=  Convert.ToDouble(root.SelectSingleNode( " /Common/Rate " ).Value);
            _charge.ScceedNumber 
=  _member.GetCurrentSucceedNumber(_DataID, _DataType);
            _charge.Charge();

            
// 修改会员类型
             if  (_member.GetChargeSum(_EnterpriseID)  >   10000 )
                _member.UpdateMemberType(_EnterpriseID, 
" Business " );

            
if  (_member.GetChargeSum(_EnterpriseID)  >   100000 )
                _member.UpdateMemberType(_EnterpriseID, 
" Luxury " );
        }
    }
}

这时,增加收费功能后,Windows Service实现的PublisherEngine只增加两行代码
Cash cash = new Cash(data.EnterpriseID,data.DataID,data.DataType);
cash.Charge();


详细代码如下:
ContractedBlock.gif ExpandedBlockStart.gif PublisherEngine
None.gifusing System;
None.gif
using System.Collections.Generic;
None.gif
using System.ComponentModel;
None.gif
using System.Data;
None.gif
using System.Diagnostics;
None.gif
using System.ServiceProcess;
None.gif
using System.Messaging;
None.gif
using System.Text;
None.gif
using System.Xml;
None.gif
using PublisherEngine.Engine;
None.gif
None.gif
namespace PublisherEngine
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
public partial class PublisherService : ServiceBase
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
private IRouterIterator iterator =  new RouterList();
InBlock.gif
InBlock.gif        MessageQueue messageQueue 
= new System.Messaging.MessageQueue();
InBlock.gif        
public PublisherService()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            InitializeComponent();
InBlock.gif            messageQueue.ReceiveCompleted 
+= new ReceiveCompletedEventHandler(messageQueue_ReceiveCompleted);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected override void OnStart(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
//可调用webservice获取站点信息,创建RouterList路由集合类
InBlock.gif

InBlock.gif                
string queuePath = "";//从配置文件中获取
InBlock.gif
                messageQueue.Path = queuePath;
InBlock.gif
InBlock.gif                messageQueue.BeginReceive();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (System.Messaging.MessageQueueException ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(ex.Message);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(ex.Message);
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
protected override void OnStop()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void messageQueue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Message message 
= messageQueue.EndReceive(e.AsyncResult);
ExpandedSubBlockStart.gifContractedSubBlock.gif                message.Formatter 
= new XmlMessageFormatter(new String[] dot.gif"System.String,mscorlib" });
InBlock.gif
InBlock.gif                DoMessage(message);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch (Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                Console.WriteLine(ex.Message);
ExpandedSubBlockEnd.gif            }

InBlock.gif            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                messageQueue.BeginReceive();
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
private void DoMessage(Message message)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            XmlDocument docMessage 
= new XmlDocument();
InBlock.gif
InBlock.gif            docMessage.LoadXml(message.Body.ToString());
InBlock.gif            XmlNode nodeMessage 
= docMessage.DocumentElement;
InBlock.gif
InBlock.gif            
//解析获取信息nodeMessage,创建data
InBlock.gif
            Data data = new Data();
InBlock.gif
InBlock.gif            iterator.First();
InBlock.gif            
while (iterator.MoveNext())
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                IRouter router 
= iterator.Current;
InBlock.gif                
if (data.WebSiteList.Contains(router.ID))
InBlock.gif                    router.PublishTo(data);
ExpandedSubBlockEnd.gif            }

InBlock.gif
InBlock.gif            
//##########增加收费功能之后增加的代码2008年1月23日##########
InBlock.gif
            Cash cash = new Cash(data.EnterpriseID,data.DataID,data.DataType);
InBlock.gif            cash.Charge();
InBlock.gif            
//####################
ExpandedSubBlockEnd.gif
        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

SmartPublisher业务逻辑层和发布引擎设计讨论到此为止,下篇将讨论UI表示层设计。

转载于:https://www.cnblogs.com/ruochen/archive/2008/01/23/1047790.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值