当前位置: 首页 > article >正文

C#设计模式——抽象工厂模式(重点)


文章目录

  • 项目地址
  • 一、抽象工厂模式
    • 1.1 特性
    • 1.2 使用反射获取特性标记的类
    • 1.3 完整代码


项目地址

  • 教程作者:
  • 教程地址:
  • 代码仓库地址:
  • 所用到的框架和插件:
dbt 
airflow

一、抽象工厂模式

  1. 工厂方法模式依然存在一个问题就是,一堆的 switch用来根据符号判断;if或者switch都是描述了一段关系,运算符和具体工厂对象的对应关系,如何直接根据符号就可以自动获取对应的类,并且自动创建实例呢?

1.1 特性

  • 什么是特性?
    通过Attribute特性,根据输入的符号,直接将符号+和cal = new Add();对应起来,特性类似于一个装饰器,装饰器装饰的类,就拥有了这个对应关系;
    往往和反射一起结合使用
  1. 创建一个特性,用来描述运算符和具体类的关系
//①使用特性Attribute来标记类的作用
public class OperToFactoryAttribute : Attribute
{
    public string Oper { get; } 
    public OperToFactoryAttribute(string oper)
    {
        this.Oper = oper;
    }
}
  1. 使用创建好的特性去标记运算类
//②使用特性Attribute来标记类的作用
//2.通过子类实现加法的创建
[OperToFactoryAttribute("+")]
public class AddFactory : ICalFactory
{
    public ICal GetCalculator()
    {
        return new Add();
    }
}

至此,运算符和对应需要的类已经创建完成,程序运行后,当用户输入了符号,我们应该通过这个对应关系,就可以找到这个类,然后进行实例化,计算

1.2 使用反射获取特性标记的类

  1. 根据用户的操作符,返回一个对象,
  2. 通过字典来存储对应关系
  3. 通过反射获取所有的程序集
  4. 获取所有的类型
  5. 通过判断获取AddFactory,SubFactory,MulFactory,DivFactory,找到他们的共性,都是继承了ICalFactory接口,并且排除ICalFactory自己

1.3 完整代码


using System.ComponentModel;
using System.Reflection;

public class program
{
    static void Main()
    {
        Console.WriteLine("输入number1:");
        double d1 = Convert.ToDouble(Console.ReadLine());

        Console.WriteLine("输入number2:");
        double d2 = Convert.ToDouble(Console.ReadLine());
        Console.WriteLine("输入运算符:");
        string op = Console.ReadLine();

        //13.执行反射里的构造函数,创建符号和类的对应关系的字典
        ReflectionFactory rf = new ReflectionFactory();
        //15.通过运算符来创建工厂
        ICalFactory calFactory = rf.CreateFactory(op);
        //16.通过具体的运算类来计算结果
        ICal calculator = calFactory.GetCalculator();
        double res = calculator.getResult(d1, d2);
        Console.WriteLine(res);

    }
}

//1.创建特性Attribute来标记类的作用
public class OperToFactoryAttribute : Attribute
{
    public string Oper { get; } 
    public OperToFactoryAttribute(string oper)
    {
        this.Oper = oper;
    }
}

//声明一个接口,先将创建对象的这个过程封装成抽象
public interface ICalFactory
{
    ICal GetCalculator();
}

//3.通过反射,程序运行后,获取特性标记的类,然后通过反射创建对象
public class ReflectionFactory
{
    //4.创建字典,存储符号和类的对应关系
    Dictionary<string, ICalFactory> dic = new Dictionary<string, ICalFactory>();
    //5.构造函数
    public ReflectionFactory()
    {
        //6.通过反射获取所有的程序集
        Assembly asm = Assembly.GetExecutingAssembly();
        //7.获取所有的类型
        Type[] types = asm.GetTypes();
        foreach (var type in types)
        {
            //8.通过判断获取AddFactory,SubFactory,MulFactory,DivFactory
            if (typeof(ICalFactory).IsAssignableFrom(type) && !type.IsInterface)
            {
                //9.获取特性
                OperToFactoryAttribute otfa = type.GetCustomAttribute<OperToFactoryAttribute>();
                //10.判断是否为空
                if (otfa != null)
                {
                    //11.将特性和类的对应关系存储到字典中,根据type创建对象
                    dic.Add(otfa.Oper, Activator.CreateInstance(type) as ICalFactory);
                }
            }
        }
    }

    //12.通过运算符来创建工厂
    public ICalFactory CreateFactory(string oper)
    {
        //13. 从字典里查找对应关系
        if (dic.ContainsKey(oper))
        {
            return dic[oper];
        }
        return null;
    }
}

//2.使用特性Attribute来标记类的作用
[OperToFactoryAttribute("+")]
public class AddFactory : ICalFactory
{
    public ICal GetCalculator()
    {
        return new Add();
    }
}

[OperToFactoryAttribute("-")]
public class SubFactory : ICalFactory
{
    public ICal GetCalculator()
    {
        return new Sub();
    }
}

[OperToFactoryAttribute("*")]
public class MulFactory : ICalFactory
{
    public ICal GetCalculator()
    {
        return new Mul();
    }
}

[OperToFactoryAttribute("/")]
public class DivFactory : ICalFactory
{
    public ICal GetCalculator()
    {
        return new Div();
    }
}

//计算类的接口
public interface ICal
{
    double getResult(double num1, double num2);
}


public class Add : ICal
{
    public double getResult(double num1, double num2)
    {
        return num1 + num2;
    }
}
public class Sub : ICal
{
    public double getResult(double num1, double num2)
    {
        return num1 - num2;
    }
}

public class Mul : ICal
{
    public double getResult(double num1, double num2)
    {
        return num1 * num2;
    }
}

public class Div : ICal
{
    public double getResult(double num1, double num2)
    {
        return num1 / num2;
    }
}


http://www.kler.cn/a/413311.html

相关文章:

  • PMP好考吗,有多大的价值?
  • 多输入多输出 | Matlab实现TCN-LSTM时间卷积神经网络结合长短期记忆神经网络多输入多输出预测
  • 数据结构(Java版)第四期:ArrayLIst和顺序表(上)
  • nrm镜像管理工具使用方法
  • Elasticsearch与CCS跨集群搜索:深入讲解与实战演练
  • k8s 架构详解
  • Python使用ffmpeg进行本地视频拉流,并使用训练模型识别人脸,并将识别后的模型推流源码
  • frida_hook_libart(简单解释)
  • 介绍SSD硬盘
  • C#里怎么样使用LINQ的let关键字实现查询?
  • 基于Qt实现的自定义树结构容器:设计与应用
  • 摄像头原始数据读取——ffmpeg(av_read_frame)
  • springboot学习-分页/排序/多表查询的例子
  • 如何在CodeIgniter中添加或加载模型
  • 2024年11月24日Github流行趋势
  • 道格拉斯-普克算法(Douglas-Peucker algorithm)
  • Android Audio实战——音频多声道基础适配(七)
  • windows 服务器角色
  • 使用guzzlehttp异步多进程实现爬虫业务
  • 【SpringCloud详细教程】-04-服务容错--Sentinel
  • Fiddler导出JMeter脚本插件原理
  • 安卓 获取 喇叭 听筒 音频输出流 AudioPlaybackCapture API 可以捕获音频输出流
  • 如何提升爬虫的效率和稳定性?
  • 【WRF后处理】WRF模拟效果评价及可视化:MB、RMSE、IOA、R
  • tcp、http、rpc的区别
  • 设计模式之破环单例模式和阻止破坏