在重构的方法中,多有提到利用多态性来替换switch/if else,并常常给出类似如下的代码。class Employee
{
double payAmt(int type)
{
double amt = 0;
switch (type)
{
case 1:
amt = 1;
break;
case 2:
amt = 2;
break;
default:
break;
}
return amt;
}
}
我试着做了如下改变, 并把问题写在注释里。
class Employee
{
int type;
public Employee(int type)
{
this.type = type;
} void main()
{
IEmployee employee;
//type该如何使用
//这里是不是还需要条件语句来做判断……
//或者这里如何达到如上switch的作用,根据type判断是该new一个什么类
employee = new Engineer();
employee.PayAmt();
}
}
interface IEmployee
{
double PayAmt();
}
class Engineer : IEmployee
{
public double PayAmt()
{
return 3000;
}
}
class Salesman : IEmployee
{
public double PayAmt()
{
return 5000;
}
}
class Manager : IEmployee
{
public double PayAmt()
{
return 10000;
}
}
{
double payAmt(int type)
{
double amt = 0;
switch (type)
{
case 1:
amt = 1;
break;
case 2:
amt = 2;
break;
default:
break;
}
return amt;
}
}
我试着做了如下改变, 并把问题写在注释里。
class Employee
{
int type;
public Employee(int type)
{
this.type = type;
} void main()
{
IEmployee employee;
//type该如何使用
//这里是不是还需要条件语句来做判断……
//或者这里如何达到如上switch的作用,根据type判断是该new一个什么类
employee = new Engineer();
employee.PayAmt();
}
}
interface IEmployee
{
double PayAmt();
}
class Engineer : IEmployee
{
public double PayAmt()
{
return 3000;
}
}
class Salesman : IEmployee
{
public double PayAmt()
{
return 5000;
}
}
class Manager : IEmployee
{
public double PayAmt()
{
return 10000;
}
}
*****************************************************************************
欢迎使用CSDN论坛专用阅读器 : CSDN Reader(附全部源代码) http://feiyun0112.cnblogs.com/
{
IEmployee employee;
public Employee(IEmployee employee)
{
this.employee = employee;
} public void main()
{
employee.PayAmt();
}
}
public interface IEmployee
{
double PayAmt();
}
public class Engineer : IEmployee
{
public double PayAmt()
{
return 3000;
}
}
public class Salesman : IEmployee
{
public double PayAmt()
{
return 5000;
}
}
public class Manager : IEmployee
{
public double PayAmt()
{
return 10000;
}
}
你看看这是不是你想要的吧。
调用的时候可以这样用:Employee e = new Employee(new Engineer());
e.main();
employee = (IEmployee)Assembly.GetExecutingAssembly().CreateInstance("ConsoleApplication1.Engineer"); Employee e = new Employee(new Engineer());
可能我太偏激了(面向对象基础太差),我的问题是该如何根据type让main()知道它是该new一个Engineer还是Salesman,或者是其他……
Employee e = new Employee(new Engineer());
Employee e = new Employee(new Salesman());
Employee e = new Employee(new Manager());你用这3种方式创建对象,当你调用main方法的时候,就会调用相应具体类(Engineer、Salesman或Manager)的PayAmt方法了。你试一下就知道了,在main方法里把employee.PayAmt();的返回值输出来看一下就清楚了。
具体做法
1.引入 using Systems.Reflection; //引用名字空间
2,IEmployee result=(IEmployee)Assembly.load("当前程序集名称").CreateInstance("当前命名空间名称.Salesman(/Manager/Engineer )")
原理就是这样,实际上后面只是一个组合好的字符串(当前命名空间名称.Salesman),根据你的type,你将字符串组合好就OK,就可得到你想new的类
是的。假如情景是这样:
用户控件UC有一个属性Type,他被放到一个页面P,P中UC.Type=1.
我应该不能在UC的main中去写出new所有的employee吧。
(可能我跳进一个坑里去了……)所以我还是需要根据一个switch or if else来告诉反射需要获得的类名……
name=type1,value="当前命名空间名称.Engineer"
name=type2,value="当前命名空间名称.Sales"//使用时
employee = (IEmployee)Assembly.GetExecutingAssembly().CreateInstance(ConfigurationManager.AppSettings["type"+this.type.ToString()]);
{
double PayAmt();
}
class Engineer : IEmployee
{
public double PayAmt()
{
return 3000;
}
}
class Salesman : IEmployee
{
public double PayAmt()
{
return 5000;
}
}
class Manager : IEmployee
{
public double PayAmt()
{
return 10000;
}
} class Employee
{
//int type;
public IEmployee iEmployee = null;
public Employee(IEmployee iEmployee)
{
this.iEmployee = iEmployee;
}
} private void button1_Click(object sender, EventArgs e)
{
double value1 = new Employee(new Engineer()).iEmployee.PayAmt();
double value2 = new Employee(new Salesman()).iEmployee.PayAmt();
double value3 = new Employee(new Manager()).iEmployee.PayAmt();
}
{
double PayAmt();
}
class Engineer : IEmployee
{
public double PayAmt()
{
return 3000;
}
}
class Salesman : IEmployee
{
public double PayAmt()
{
return 5000;
}
}
class Manager : IEmployee
{
public double PayAmt()
{
return 10000;
}
} class Employee
{
//int type;
public IEmployee iEmployee = null;
public Employee(int type)
{
switch (type)
{
case 1:
iEmployee = new Engineer();
break;
case 2:
iEmployee = new Salesman();
break;
case 3:
iEmployee = new Manager();
break;
default:
break;
}
//this.iEmployee = iEmployee;
}
} private void button1_Click(object sender, EventArgs e)
{
double value1 = new Employee(1).iEmployee.PayAmt();
double value2 = new Employee(2).iEmployee.PayAmt();
double value3 = new Employee(3).iEmployee.PayAmt();
}
有2种方法吧。
1、为控件定义一个公开的属性
IEmployee _emp;
public IEmployee Emp
{
get { return _emp; }
set { _emp = value; }
}
在page里面,你可以用UC.Emp = new Employee(new Engineer());来传递真正的实例2、依然保留Type
在页面依然可以用UC.Type=1,而你在main方法里根据Type的值来决定实例化哪个具体类
至于根据Type怎么实例化具体类,最简单的用switch,但具体类多了也不好。
如果希望方便的话,可以用反射,加上配置文件,如下:
(IEmployee)System.Reflection.Assembly.Load("程序集名称").CreateInstance("具体类的完整名,包括命名空间");
你错误地假设了应用场景,所以误导了之下许多人都去按照你的错误场景去“解决”,甚至去想到了“反射”?!我们开发一个通用的处理过程,可以处理通用的凡是实现IEmployee的对象,是要把这个过程放到一个“工具箱”里。然后当什么时候有个客户需要这个功能的时候,拿出来就用就好了。就好像一把螺丝起子可以拧很多种螺丝一样。而你给出的场景是在“Main()”这个作为发起操作的最终客户中,想去规定什么业务逻辑吗?有什么意义?为谁进行抽象?面向对象设计的场景是:你需要设计一个专门产品报价单对象,它包括多个产品项目,每一个产品就是一个IEmployee,于是这个报价单对象可以输出总金额:foreach(emp in this.Employees)
sum += emp.PayAmt();而产品有很多种,在你设计这个报价单对象(类)的时候根本不知道将来会多少新的Employee种类。
你看,你在开发的时候根本不在乎被设计处理的对象的具体子类有多少,只要抽象到同样的类型(接口)就可以,这样才体现你是基于抽象来设计的。
而你的那种责问“Main中如何去匹配type变量的值”的初衷,不适合考虑抽象化。只是知道需要去为眼前编写一个试用软件,而不是去设计一个长期使用的通用工具。
sum += emp.PayAmt(); 少写了类型声明。
我想我的原意是想请教怎么把switch弄掉。 而在面向对象思想上,我又混淆了概念。我想再请问,我所设定的这个场景中,面向对象设计是如何体现的,type的那部分(反射或者暴露的IEmployee)和UC的最终输出又该怎么去理解他在面向对象设计中的位置(作用)?我的初衷,
1. 面向对象设计体现在接口的定义和实现接口的类。
2. type部分利用配置文件的值和反射得到具体一个实例化的对象(该算是面向对象之后的应用吧)。