前言: 我本是山中散修,在这残忍的修仙界举步维艰,本以为这辈子都只能在练气期徘徊,偶得神秘Jan佬相助,传我天界功法,待我练成此功法,必
一日筑基,两日金丹,三日大帝!
(本文章知识点:面对对象,封装,继承,多态,耦合)
第一章:代码无错就是优?
让你实现一个计算器功能,你会如何实现,有人会想,卧槽,这还不简单 直接:
class Program {
static void Main (string[] args){
Console.Write("请输入数字A:");
string A = Console.ReadLine () ;
Console.Write("请选择运算符号(+、-、*、/):");
string B = Console.ReadLine ();
Console.Write("请输入数字B:");
string C = Console.ReadLine ();
string D = "";
if (B == "+")
D = Convert.ToString (Convert.ToDouble (A) + Convert.ToDouble (C)) ;
if (B == "-")
D = Convert.Tostring (Convert.ToDouble (A) - Convert.ToDouble (C));
if (B == "*")
D = Convert.ToString (Convert.ToDouble (A) * Convert.ToDouble (C) ) ;
if (B == "/")
D = Convert.ToString (Convert.ToDouble (A) / Convert.ToDouble (C)) ;
Console.WriteLine ("结果是:" + D);
}
}
上面的问题:
1.命名问题:命名非常不规范 a,b,c,d,让人无法直观的知道这些变量代表上面意思
2.判断分支:我们应该只需要判断是哪个符号就可以了,而不是每个都走一遍,
3.优化问题:如果用户输入/号,并且除数为0(0不能作为除数)?用户输入的不是数字,是字符串呢? (解决上述问题并不难,这里就不写答案了)
封装: 如果我们需要在另一个地方也要用到该 Program 类,如何去做呢,新手可能会想:"简单,复制粘贴一下不就可以了 吗",这是不好的想法,
借助书中原话:”当你的代码中重复的代码多到一定程度,维护的时候,可能就是一场灾难。越大的系统,这种方式带来的问题越严重,编程有一原则,就是用尽可能的办法去避免重复。“
如何解决? 让 业务逻辑 和 界面逻辑 分开,让他们的 耦合度 下降 运算类
public class Operation
public static double GetResult (double numberA, double numberB, string operate){
double result = 0d;
switch (operate)
{
case "+"
result = numberA + numberB;
break;
case "-"
result= numberA - numberB;
break;
case "*"
result= numberA * numberB;
break;
case "/":
result = numberA / numberB;
break;
}
return result;
}
客户端:
static void Main(string[] args){
try{
Console.Write("请输入数字A:");
string strNumberA = Console.ReadLine();
Console.Write("请选择运算符号(+、-、*、/:");
string strOperate = Console.ReadLine();
Console.Write("请输入数字B:");
string strNumberB = Console.ReadLine();
double result = Operation.GetResult(Convert.ToDouble(strNumberA), Convert.ToDouble(strNumberB), strOperate);
Console.WriteLine("结果是: " + result);
}
}
继承 多态 这看起来很灵活了吧,那假如让你 修改 或 拓展 代码呢,让你加入一个 开平方根的功能 ,这并不需要加减乘除的运算参与编译,你却不小心把加法改成减法,这不完蛋了
解决思路:把加减乘除的运算分离出来
Operation运算类
public class Operation {
private double_numberA = 0
private double_numberB = 0;
public double NumberA {
get { return_numberA; }
set { numberA = value; }
}
public double NumberB {
get { return numberB; }
set { numberB = value; }
}
public virtual double GetResult() {
double result = 0;
return result;
}
}
加减乘除类(继承运算类,分出多个类,也就是多态)
class OperationAdd :Operation {
public override double GetResult()
{
double result =0
result = NumberA + NumberB;
return result
}
}
class ... (以此类推,怕太长了)
这样就可以了, 我们通过GetResult()方法来获取值,也可以通过GetResult()方法的重写来重新获取值,这样我们就不需要提供其他算法的代码了
接下来实例化对象,我们要实例化谁,将来会不会增加实例化的对象,就比如刚才的开平方
public class OperationFactory
{
public static Operation createOperate (string operate)
{
Operation oper = null;
switch (operate)
{
case "+":
oper = new OperationAdd ();
break;
case "-":
oper = new OperationSub ();
break;
case "*":
oper = new OperationMul ();
break;
case "/":
oper = new OperationDiv ();
break;
}
return oper;
}
}
这样,只需要输入运算符号,就能通过实例化出合适的对象,通过 多态放回父类方法实现计算结果
Operation oper;
oper = OperationFactory.createOperate( "+" );
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult();//3
最后看图加深印象
最后来看第一章最后的内容:uml类图
初看很难,没关系,讲解一下就理解了
动物 是第一层,他和氧气和水为依赖关系,因为离开他就会死(在代码中,没有他就无法进行)
鸟 是第二层(继承 动物,获取动物的 属性 和 方法)
翅膀 也是第二层 他和鸟为组合关系 一种强 ’拥有关系‘(因为鸟都有翅膀)
大雁 鸭 企鹅 都为 第三层 他们各有各的特点(继承 翅膀, 各有各的方法)
比如大雁是能飞的,所有他可以有飞翔接口,大雁和雁群,每只大雁都属于一个雁群,一个雁群可以有多只大雁,就满足 聚合关系(加入雁群有a,b,c大雁,我可以只用a,c大雁)
企鹅需要‘了解’气候的变化才能下蛋,他和气候 为 关联关系,(当一个类’知道‘另一个类时,可以关联起来)
唐老鸭算第四层,因为他继承了鸭,新加入了 讲人话方法
结语: 浓缩精华真的难啊