方式1(传统方式)调用方: ClassTest test=new ClassTest(); test.fun1(string param1,int param2); 方法实现类(Class ClassTest): public void fun1(string param1,int param2) { // do something... }方式2(参数通过属性)调用方: ClassTest test=new ClassTest(); test.Param1="aaa"; test.Param2=2; test.fun1(); 方法实现类(Class ClassTest): public class ClassTest { public string Param1{get;set;} public string Param2{get;set;} public void fun1() { // do something used Param1 and Param2 } }
不就是 public Int i1; 和 public Int I1{get;set} pravit int i1; 的区别吗设计成属性,就可以用get和set方法来校验输入的值,确保不会在类的外部把全局变量赋值成一个非法的数字 而且有些变量必须是只读的,不允许在外部修改的
这是代码:方式1(传统方式) 调用方: ClassTest test=new ClassTest(); test.fun1(string param1,int param2); 方法实现类(Class ClassTest): public void fun1(string param1,int param2) { // do something... }方式2(参数通过属性) 调用方: ClassTest test=new ClassTest(); test.Param1="aaa"; test.Param2=2; test.fun1(); 方法实现类(Class ClassTest): public class ClassTest { public string Param1{get;set;} public string Param2{get;set;} public void fun1() { // do something used Param1 and Param2 } }
我5楼说的是传统api使用上的问题下面你既然提到了面对对象,ok,我们说传统api是明显的过程式编码,你怎么会认为怎么明显的过程式代码风格会比封装滴对象更符合面对对象呢??对象有一个和过程式明显的区别是“抽象”,各个方法强调的是依赖抽象,而非依赖具象。比如一个用户对象,我依赖滴只是用户对象,并不依赖你里面有什么用户名啊,用户密码啊,出身年月啊。ps:作为基本设计,只有类似math.abs,math.cos,这样具有明确含义的方法是需要确定参数滴,而且业务逻辑,其实只依赖业务抽象,而不依赖具体每一个参数。 比如 一个where,我们依赖滴是func<T,bool>,你如果俺传统api,你会写什么。你会写 参数1,参数2,如何拼接sql语句,where 参数1=xx and 参数2=xxx
不要一刀切 举一个列子 比如 两个数相加Add(int a, int b)// 你觉得这个好,还是下面的一个好public class TwoNum { public int NumA; public int NumB; } Add(TwoNum nums)我现在的设计依据是:如果参数很多~而且参数个数不固定那么用对象,反过来参数很少,而且很固定,param1 param2
我不觉得这样设计有多好,甚至我觉得这样子有些代码坏味道。1.从封装角度看。这样的方法签名,表达能力不强,没交代清楚输入,调用者需要了解被调用代码细节,才能知道需要给哪些属性赋值。如果不同程序集,不同人员一同开发会有不小沟通障碍,一旦被调用方法参数有变要通知调用方,否则可能出现bug。2.从接口角度看。基于第一点,很难形成接口,因为接口功能之一是定义输入输出的规范。 3.从维护角度看。 首先,代码是你自己写的,自然觉得问题不大,但是如果别人来做代码的维护,单看调用不看被调用方法的代码细节,确实不知道怎么改。其次,如果被调用方法所需参数数量发生变化时,那么调用代码的对象实例的属性需要相应的新增和修改,这个做不到自动重构,需要查找引用,然后手工一个个改,可能存在漏改;如果不改,多余的属性赋值显然会影响以后阅读。如果是指明参数个数和类型,起码编译的时候可以报错。 4.从隐藏Bug角度看。基于第三点,如果被调用方法体内部对参数使用个数等的修改,然后,调用没有同步修改,可能隐含造成bug(方法体新增参数的时候,调用没有同步新增属性的赋值)。 5.从泛型编程角度看。这样子的设计,难用泛型来编程,因为你需要给具体类型的具体属性赋值后才调用方法。如果按照这样的思路,我一般更倾向于使用实体类作为参数。例如://以下DAO public IDAO<TEntity> where TEntity : EntitieBase, new() { Add(TEntity); Update(TEntity); }public abstract class DAOBase<TEntity, TDataContext> : IDAO<TEntity> where TEntity : EntitieBase, new() where TDataContext : DbContext, new() { protected TDataContext dataContext; public TDataContext DataContext { get { return dataContext; } }
方式1(传统方式)调用方:
ClassTest test=new ClassTest();
test.fun1(string param1,int param2);
方法实现类(Class ClassTest):
public void fun1(string param1,int param2)
{
// do something...
}方式2(参数通过属性)调用方:
ClassTest test=new ClassTest();
test.Param1="aaa";
test.Param2=2;
test.fun1();
方法实现类(Class ClassTest):
public class ClassTest
{
public string Param1{get;set;}
public string Param2{get;set;}
public void fun1()
{
// do something used Param1 and Param2
}
}
public Int i1;
和
public Int I1{get;set}
pravit int i1;
的区别吗设计成属性,就可以用get和set方法来校验输入的值,确保不会在类的外部把全局变量赋值成一个非法的数字
而且有些变量必须是只读的,不允许在外部修改的
ClassTest test=new ClassTest();
test.fun1(string param1,int param2);
方法实现类(Class ClassTest):
public void fun1(string param1,int param2)
{
// do something...
}方式2(参数通过属性) 调用方:
ClassTest test=new ClassTest();
test.Param1="aaa";
test.Param2=2;
test.fun1();
方法实现类(Class ClassTest):
public class ClassTest
{
public string Param1{get;set;}
public string Param2{get;set;}
public void fun1()
{
// do something used Param1 and Param2
}
}
自定义一个textbox控件
那么你要把它的text属性赋值为null,是绝对不允许的行为
而且赋值之后,显示的文字要刷新,那么赋值之后就要立即执行刷新的方法,而不是又在外部手动去刷新
如果赋值跟它现在的值相同,则不必多余的去执行一遍刷新的方法还有,textbox有位置,高度,宽度的属性,还有range属性(所在的区域),位置和宽高确定了,range也就确定了,range必须是只读的,不能另外改成别的东西这些就是声明为属性的好处,比直接定义成public的变量直接修改要好的多
比如fun1()需要用到p1和p2
fun2()需要用到p1
fun3()需要用到p2
那么如果需要对输入的参数进行控制,比如范围必须在1-100之间之类的
就不需要在fun1(),fun2(),fun3()里分别判断许多次,而只在set里判断一次就足够了
但是这样不利于扩展,比如将来还会有fun4,fun5,都要用到p1和p2,
那么如果将来定义fun4的时候,忘记将这个函数复制过来再执行一遍,不就出错了吗
你怎么知道人家不是弄500个class,而非得是一个class呢?实际上你既没有理解为什么要弄class,也没有理解为什么(带参数或者无参数的)方法要定义在对象中。
你怎么知道人家不是弄500个class,而非得是一个class呢?实际上你既没有理解为什么要弄class,也没有理解为什么(带参数或者无参数的)方法要定义在对象中。500 改为 100!
比如 一个where,我们依赖滴是func<T,bool>,你如果俺传统api,你会写什么。你会写 参数1,参数2,如何拼接sql语句,where 参数1=xx and 参数2=xxx
不要一刀切 举一个列子 比如 两个数相加Add(int a, int b)// 你觉得这个好,还是下面的一个好public class TwoNum
{
public int NumA;
public int NumB;
}
Add(TwoNum nums)我现在的设计依据是:如果参数很多~而且参数个数不固定那么用对象,反过来参数很少,而且很固定,param1 param2
3.从维护角度看。
首先,代码是你自己写的,自然觉得问题不大,但是如果别人来做代码的维护,单看调用不看被调用方法的代码细节,确实不知道怎么改。其次,如果被调用方法所需参数数量发生变化时,那么调用代码的对象实例的属性需要相应的新增和修改,这个做不到自动重构,需要查找引用,然后手工一个个改,可能存在漏改;如果不改,多余的属性赋值显然会影响以后阅读。如果是指明参数个数和类型,起码编译的时候可以报错。
4.从隐藏Bug角度看。基于第三点,如果被调用方法体内部对参数使用个数等的修改,然后,调用没有同步修改,可能隐含造成bug(方法体新增参数的时候,调用没有同步新增属性的赋值)。
5.从泛型编程角度看。这样子的设计,难用泛型来编程,因为你需要给具体类型的具体属性赋值后才调用方法。如果按照这样的思路,我一般更倾向于使用实体类作为参数。例如://以下DAO
public IDAO<TEntity> where TEntity : EntitieBase, new()
{
Add(TEntity);
Update(TEntity);
}public abstract class DAOBase<TEntity, TDataContext> : IDAO<TEntity>
where TEntity : EntitieBase, new()
where TDataContext : DbContext, new()
{
protected TDataContext dataContext; public TDataContext DataContext
{
get { return dataContext; }
}
Add(TEntity)
{
DataContext.Add(TEntity);
TEntity.ID = Guid.newd.tos();
}
}public class DaoUser : DAOBase<User, EFEntities>
//以下BO
public abstract class BOBase<TEntity, TIDAO>
where TEntity : EntitieBase
where TIDAO : IDAO<TEntity>
{
protected ICacheManager CacheManager;
protected ILogManager LogManager;
protected ITranstionManager TranstionManager;
protected <T>ServiceLocator
{
//ioc容器
} private TIDAO dao; public TIDAO Dao
{
get
set
}
Add(TEntity)
{
Dao.Add(TEntity);
}
}public class BoUser : BOBase<User, DaoUser>