设计模式

0 阅读4分钟

前言: 我本是山中散修,在这残忍的修仙界举步维艰,本以为这辈子都只能在练气期徘徊,偶得神秘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

最后看图加深印象

微信图片_2026-03-13_171505_988.jpg

最后来看第一章最后的内容:uml类图

微信图片_2026-03-13_171825_379.jpg

初看很难,没关系,讲解一下就理解了

动物 是第一层,他和氧气和水为依赖关系,因为离开他就会死(在代码中,没有他就无法进行)

是第二层(继承 动物,获取动物的 属性方法)

翅膀 也是第二层 他和鸟为组合关系 一种强 ’拥有关系‘(因为鸟都有翅膀)

微信图片_2026-03-13_174134_548.jpg

大雁 鸭 企鹅 都为 第三层 他们各有各的特点(继承 翅膀, 各有各的方法)

比如大雁是能飞的,所有他可以有飞翔接口,大雁和雁群,每只大雁都属于一个雁群,一个雁群可以有多只大雁,就满足 聚合关系(加入雁群有a,b,c大雁,我可以只用a,c大雁)

微信图片_2026-03-13_174245_986.jpg

企鹅需要‘了解’气候的变化才能下蛋,他和气候 为 关联关系,(当一个类’知道‘另一个类时,可以关联起来)

唐老鸭算第四层,因为他继承了鸭,新加入了 讲人话方法

结语: 浓缩精华真的难啊