简单工厂模式——选择实现

问题引入

请用C++、Java、C#或VB.NET任意一种面向对象语言实现一个计算器控制台程序,要求输入两个数和运算符号,得到结果。
新手最简单的写法

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);
  
 }
}

这样写的缺点

  • 变量命名不规范
  • 该判断分支会使计算机做无用功
  • 被除数缺少规范

稍加修改

A改为strNumberA
B改为strOperate
C改为strNumberB
if改为switch结构
除之前加上不等于0的判断

修改后还存在什么问题
编码过于结构化,未能体现面向对象的思想,具体体现在

  • 不易维护(修改任何一个计算细节都会影响整个系统)
  • 不易拓展(拓展时会先破坏这个类)
  • 不易复用

面向对象与结构化编程的优点

  • 可维护
  • 可复用
  • 可拓展
  • 灵活性好

问题思考

面向对象编程的三大特性

学习了面向对象,应考虑如何通过封装、继承、多态把程序的耦合度降低,如何使用设计模式使得程序更加的灵活,容易修改,并且易于复用

复制和复用

编程有一原则,就是用尽可能的办法去避免重复,考虑代码,有哪些是和控制台无关的,而只是和计算器有关的。如何让计算和显示分离,如何让业务逻辑和界面逻辑分离等。

封装时考虑紧耦合与松耦合

上述程序在修改时存在不安全性,当增加一个计算功能组件时,需要将整个类重新编译,修改时可能出错。类内耦合过紧,不利于维护

工厂模式

工厂模式简介

工厂模式专门负责将大量有共同接口的类实例化。工厂模式可以动态决定将哪个类实例化,不必事先知道每次要实例化哪个类。工厂模式有以下几种形态:简单工厂(SimpleFactory)模式、工厂方法模式(FactoryMethod)模式、抽象工厂(AbstractFactory)模式

简单工厂模式

SimpleFactory模式根据提供给它的数据,返回几个有可能类中的一个类的实例。通常它返回的类都有一个公共的父类和公共的方法。
在这里插入图片描述
工厂角色Creator(简单工厂类):工厂类在客户端的直接控制下创建产品对象。
抽象产品角色Product(产品类):定义简单工厂创建的对象的父类或它们共同拥有的接口。可以是一个类、抽象类或接口。
具体产品角色ConcreteProduct(产品衍生类):定义工厂具体加工出来的对象。

简单工厂模式实现计算器

抽象产品角色

 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;
        }
    }

具体产品-加法类

  public class OperationAdd:Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA + NumberB;
            return result;
        }
    }

具体产品-减法类

  public class OperationSub:Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA - NumberB;
            return result;
        }
    }

具体产品-乘法类

  public class OperationMul:Operation
    {
        public override double GetResult()
        {
            double result = 0;
            result = NumberA * NumberB;
            return result;
        }
    }

具体产品-加法类

  public class OperationDiv:Operation
    {
        public override double GetResult()
        {
           double result = 0;
            if(NumberB==0)
            {
                throw new Exception("除数不能为0.");
            }
            result = NumberA / NumberB;
            return result;
        }
    }

工厂类

  public class OperationFactory
    {
        public static Operation createOperation(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;
        }
    }

客户端

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private void btnj_Click(object sender, EventArgs e)
        {
            string ysf = cbB.Text;
            Operation oper;
            oper = OperationFactory.createOperation(ysf);
            oper.NumberA = Convert.ToDouble(tbA.Text);
            oper.NumberB = Convert.ToDouble(tbB.Text);
            double result = oper.GetResult();
            trt.Text =result.ToString();

        }
        private void button1_Click(object sender, EventArgs e)
        {
            cbB.Text = "";
            tbA.Text = "";
            tbB.Text = "";
            trt.Text = "";
        }
        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }

客户端界面
在这里插入图片描述

典型疑问

上面实例中的简单工厂看起来不就是把客户端里面的“new OperationAdd()”移到了简单工厂里面吗?
答:接口是用来封装隔离具体的实现的,目标就是不要让客户端知道封装体内部的具体实现。简单工厂的位置是位于封装体内的,所以简单工厂知道具体类的实现是没有关系的。对于客户端来说,只是知道了接口和简单工厂。

简单工厂的优点与缺点

优点:

  • 工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品。简单工厂模式通过这种做法实现了对责任的分割。
    缺点:

  • 当产品类有复杂的等级结构时,工厂类只有自己,以不变应万变,就是模式的缺点。因为工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。

  • 同时,系统拓展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂。

  • 另外,简单工厂模式通常使用静态工厂方法,这使得无法由子类继承,造成工厂角色无法形成基于继承的等级结构

简单工厂的本质

选择实现

应用场景

  • 如果想要完全封装隔离具体实现,让外部类只能通过接口来操作封装体,则可以选用简单工厂。让客户端通过工厂来获取相应的接口,而无需关心具体的实现。
  • 如果想要八对外创建对象的职责集中管理和控制,可以选择简单工厂
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
8选1选择器可以用FPGA实现,其中FPGA是一种可编程逻辑器件,可以通过编程来实现各种数字电路。下面是一个简单的8选1选择器的FPGA实现过程: 1. 首先,我们需要使用HDL语言(如Verilog或VHDL)来描述8选1选择器的行为和功能。在这个例子中,我们使用Verilog来实现。 2. 在Verilog代码中,我们需要定义8个输入信号和1个输出信号。这些输入信号表示8个不同的输入,输出信号表示选中的输入。 3. 在代码中,我们需要使用一个3位二进制编码器来选择输入信号。这个编码器将8个输入信号编码为3位二进制数,然后将这个编码器的输出与8个输入信号的“与”门相连。 4. 最后,我们需要使用一个多路选择器来选择编码器的输出,并将其作为输出信号。这个多路选择器可以通过使用FPGA内部的LUT(查找表)来实现。 下面是一个简单的Verilog代码示例,用于实现8选1选择器: ``` module mux8to1 ( input [7:0] in, input [2:0] sel, output reg out ); always @ (*) begin case (sel) 3'b000: out = in[0]; 3'b001: out = in[1]; 3'b010: out = in[2]; 3'b011: out = in[3]; 3'b100: out = in[4]; 3'b101: out = in[5]; 3'b110: out = in[6]; 3'b111: out = in[7]; endcase end endmodule ``` 这里我们使用了一个case语句来实现多路选择器的逻辑。在这个例子中,我们定义了8个输入信号(in[0]到in[7]),一个输出信号(out),以及一个3位二进制选择器(sel)。通过使用case语句,我们可以根据选择器的值选择正确的输入信号,并将其输出到输出信号中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值