首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

类爆炸有关问题,对维护也是恶梦

2012-01-18 
类爆炸问题,对维护也是恶梦?原意在ERP项目中有设计一个工序类用來描述工序:public Process{public string

类爆炸问题,对维护也是恶梦?

原意在ERP项目中有设计一个工序类用來描述工序:
public Process
{
 
 public string ProcessNo
{
 get{}
 set{}
}
public string ProcessDesc
{
 get{}
 set{}
}
//宽Size2 属性
 public virtual float GetSize2();
 public virtual void SetSize2(float _size2);

}

如下图:
----------------------------
工序号 工序名称 Size2求法 说明
----------------------------
91 包裝 F_GetPack(Productobj obj,int X) 成品尺寸宽
95 粘合 F_GetSize2(layoutobj obj) 排版尺寸的宽
2A 过油 F_GetSize(int size1,int size2) 用户输入的值得到
.......................
99 XX F_PA() ...........

但是发现实际情况下是公司有几百个不同的工序,最主要有些工序同样的属性如(宽),不同的名字或在不同的产品时会有不同的方法求得(但不是所有的都不同)。我的问题是:
  如不同的工序用继承的方法,不同的子类重写不同的方案,会产生上百个工序类,而且将来工序会因需要自动增加,显然会产生类爆炸问题,对维护也是恶梦! 
  如不用继承的方法,转而只用写成一个类中,用不同的函数名不同的方式,显多也是太多函数,且一样不能维护。

请问各位有什么好的设计类的方案?



[解决办法]
你的问题主要是在计算方法上,所以把“size2求法”改成两部部分,算法名称和参数表。
另一个算法的注册管理类,用于添加、维护和调用算法。
所有的算法可以定义一个算法基类,有public float virtual Calc();
每个算法类用属性维护算法参数,orerride Calc()方法。并将算法类对象在算法注册管理类中注册。

[解决办法]
使用 抽象工厂 模式 管理若干的类。

这是第一步,如果按照理论来是使用 组合 方式,使用类似策略模式来处理,把不同的处理方法封装好,然后创建类的时候动态的组合这些封装好的策略,但是这仅仅是理论。

如果你的每个类对应的工序的处理过程并不是这种原料般的组合过程那就不能用这种模式。

如果在.Net环境下我推经用Hashtable把“工序名字”和“类类型名称”组合的存入。
如果在一般环境下我推荐写一个类,这个类负责管理“工序名称”到“工序处理过程”的映射,即String和函数指针的关系。

更简单的是把函数指针们用宏写入一个初始化的数组,然后用枚举。

如果完全用OO方法,我认为这种情况下你的抽象粒度是不合理的,每个工序都抽象为类是不是有点过于细,你可以考虑以后从更高的层次抽象。如果必须这么做,也可以丰富一下抽象工厂,让抽象工厂来做更多事情,比如注册一个类型,等等操作。

嗯嗯,欢迎继续讨论!
[解决办法]
给你提供一点框架的东西:

C# code
    /// <summary>    /// 工序类    /// </summary>    public class Process    {        public string ProcessNo        {            get; set;        }        public string ProcessDesc        {            get; set;        }        public CalcMethodInfo GetMethod { get; set; }        public CalcMethodInfo SetMethod { get; set; }        public float Size        {            get            {                return CalcMethodManager.Instance[GetMethod.MethodName].GetSize();            }            set            {                CalcMethodManager.Instance[SetMethod.MethodName].SetSize(value);            }        }    }    /// <summary>    /// 计算方法信息类    /// </summary>    public class CalcMethodInfo    {        public string MethodName { get; set; }        public object[] Args { get; set; }    }    /// <summary>    /// 负责计算方法注册、调用的管理类。    /// 可以考虑用配置文件,部署运行起来方便    /// </summary>    public class CalcMethodManager:Dictionary<string, CalcMethodBase>    {        /// <summary>        /// 注册计算方法        /// </summary>        /// <param name="calcMethod"></param>        public void Register(CalcMethodBase calcMethod)        {            Add(calcMethod.Name, calcMethod);        }        public static CalcMethodManager Instance = new CalcMethodManager();        CalcMethodManager()        {            //可以在此从配置文件读出方法,并登记。也可以程序中手工调用Register方法注册。        }    }    /// <summary>    /// 方法类。    ///可以考虑配置,部署运行起来方便    /// </summary>    public abstract class CalcMethodBase    {        public string Name { get; set; }        /// <summary>        /// 以下2个方法在子类中必须被重写        /// </summary>        /// <returns></returns>        public virtual float GetSize() { throw new NotImplementedException(); }        public virtual void SetSize(float value) { throw new NotImplementedException(); }    }    /// <summary>    /// 计算方法的一个实例类。    /// 可以将类的Namespace,assembly信息写入配置文件,为了CalcMethodManager可以自动读取    /// </summary>    public class CalcMethodM1:CalcMethodBase    {        public int Size1 { get; set; }        public int Size2 { get; set; }        public override float GetSize()        {            //换成需要的算法            return Size1 + Size2;        }        public override void SetSize(float value)        {            //换成需要的算法            Size1 = (int)value/2;            Size2 = (int)(value - Size1);        }    } 


[解决办法]
你先试试对工序的算法做抽象,将多个工序的算法抽象为一个双方多个参数,也许会简化一些类对象。
[解决办法]
一般情况下,不同的算法需要用不同的类封装。除非你能定义出这些不同算法的共同规律。类爆炸的情况是存在的。
当然,在你的例子里,process类是相对稳定的。应将不稳定的部分(算法)分离出来独立管理,并尽量采用配置。

[解决办法]
你可以参考下面这个简单的管理机制

C# code
Dictionary<string, Action<object>> list = new Dictionary<string, Action<object>>();            list.Add("工序1", delegate(object i) { Response.Write("我想传入int i 并打印i值,i=" + i.ToString()); });            list["工序1"].Invoke(1);
[解决办法]
这样的做法,对于调用者来说代码都是一样,无须更改

但是对于单步工序实现代码编写人员来说,那个委托还是要去写代码的。代码增长也是必须的

好在都在统一的机制下,编写还算简单(实际上codedom或j#引擎可以完成动态编译或动态运行,但是比较麻烦,不过微软已经考虑到了所以C#4.0已经加入相关动态代码功能)

如果想在目前的机制下完成,我的建议是调用管控部分,不妨使用ironPython或j#来处理,这样的还算有部分代码可以临时添加而不必编译dll并重新配置文件

热点排行