重构对象列表以实现业务规则

如何解决重构对象列表以实现业务规则

| 我需要重构以下类:
public interface IEmployee
{
    int VacationWeeks { get; }
    int YearsWithCompany { set; get; }
    double Salary { set; get; }
}

public class Employee : IEmployee
{
    private readonly int vacationWeeks;

    public Employee(int vacationWeeks)
    {
        this.vacationWeeks = vacationWeeks;
    }

    public int VacationWeeks
    {
        get { return vacationWeeks; }
    }

    public int YearsWithCompany { set; get; }
    public double Salary { set; get; }
}
我需要确保VacationWeeks仅取决于YearsWithCompany,并且正在从数据库加载映射。到目前为止,我已经提出了:
public class EmployeeNew : IEmployee
{
    private Dictionary<int,int> vacationWeeksTable;

    public EmployeeNew(Dictionary<int,int> vacationWeeksTable)
    {
        this.vacationWeeksTable = vacationWeeksTable;
    }

    public int VacationWeeks
    {
        get { return vacationWeeksTable[YearsWithCompany]; }
    }

    public int YearsWithCompany { set; get; }
    public double Salary { set; get; }
}
此类实现了我想要的功能,但仍然存在一个漏洞:可能已使用VacationWeeksTable的不同实例创建了同一集合中EmployeeNew的不同实例。 同一集合中EmployeeNew的所有实例必须引用相同的VacationWeeksTable。 我重构的应用程序在整个系统中使用了很多List,我们需要能够修改YearsWithCompany和Salary,但要保证每个List仅使用一个VacationWeeksTable。这些列表被迭代了几次;它的元素在每次迭代中都会修改。 这是我不完善的解决方案。欢迎提出建议:
// this class does two things,which I do not like
    public class EmployeeList : IEnumerable<IEmployee>,IEmployee
    {
        private Dictionary<int,int> vacationWeeksTable;
        private List<EmployeeSpecificData> employees;
        private int currentIndex;
        private EmployeeSpecificData CurrentEmployee
        {
            get { return employees[currentIndex]; }
        }

        public IEnumerator<IEmployee> GetEnumerator()
        {
            for (currentIndex = 0; currentIndex < employees.Count; currentIndex++)
            {
                yield return this;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public int VacationWeeks
        {
            get { return vacationWeeksTable[YearsWithCompany]; }
        }

        // this is ugly repetitive code I don\'t like
        public int YearsWithCompany
        {
            get { return CurrentEmployee.YearsWithCompany; }
            set { CurrentEmployee.YearsWithCompany = value; }
        }

        // this is ugly repetitive code I don\'t like
        public double Salary
        {
            get { return CurrentEmployee.Salary; }
            set { CurrentEmployee.Salary = value; }
        }


    }
    

解决方法

        我使用以下代码创建和初始化一些需要默认行为和共享行为的类。也许您可以重构它会有所帮助: 它是Factory和FlyWeight模式组合的某种形式(可以在您的方案中删除flyweight部分),此外还有类Type共享处理程序的概念。 我简化并删除了一些您不需要的东西,但还有更多要删除的地方,我添加了评论。 用法为:(应用初始化)
Dictionary<int,int> vacationWeeksTable = new Dictionary<int,int>();
// fill the table
Factory<Employee>.Init(vacationWeeksTable);
每当您创建Employee类时:
// remove grouping in the factory class to remove this null
Employee em = Factory<Employee>.Create(null);
它仅对类使用WeakReference,因此您不必担心GC。 每位员工将在创建时拥有共享的VacationWeeksTable设置,如果不使用工厂类,则无法从外部进行更改。 您可以在应用程序的运行时随时更改Employee所有正在运行的实例的假期表,方法是:
// this will call the method registered for SetInitialdata on all instances of Employee classes.
// again remove grouping to remove that null
Factory<Employee>.Call(EventHandlerTypes.SetInitialData,null,vacTable);
员工实施示例:
class Employee : IBaseClass
{
    private Dictionary<int,int> vacationWeeksTable;

    public virtual void RegisterSharedHandlers(int? group,Action<IKey,int?,EventHandlerTypes,Action<object,SharedEventArgs>> register)
    {
        group = 0; // disable different groups
        register(new Key<Employee,int>(0),group,EventHandlerTypes.SetInitialData,SetVacationWeeksTable);
    }

    public virtual void RegisterSharedData(Action<IKey,object> regData)
    {
        // remove this from factory and interface,you probably dont need it
        // I have been using it as a FlyWeight data store for classes.            
    }

    private void SetVacationWeeksTable(object sender,SharedEventArgs e)
    {
        vacationWeeksTable = e.GetData<Dictionary<int,int>>();
    }

}
代码模式实现: IBaseClass:我可以通过工厂实现创建的每个类的接口
public enum EventHandlerTypes
{
    SetInitialData // you can add additional shared handlers here and Factory<C>.Call - it.
}

public class SharedEventArgs : EventArgs
{
    private object data;

    public SharedEventArgs(object data)
    {
        this.data = data;
    }

    public T GetData<T>()
    {
        return (T)data;
    }
}

public interface IBaseClass
{
    void RegisterSharedHandlers(int? group,SharedEventArgs>> regEvent);
    void RegisterSharedData(Action<IKey,object> regData);
}
实用程序通用类:
public interface IKey
{
    Type GetKeyType();
    V GetValue<V>();
}

public class Key<T,V> : IKey
{
    public V ID { get; set; }
    public Key(V id)
    {
        ID = id;
    }

    public Type GetKeyType()
    {
        return typeof(T);
    }

    public Tp GetValue<Tp>()
    {
        return (Tp)(object)ID;
    }
}

public class Triple<T,V,Z>
{
    public T First { get; set; }
    public V Second { get; set; }
    public Z Third { get; set; }
    public Triple(T first,V second,Z third)
    {
        First = first;
        Second = second;
        Third = third;
    }
}
工厂类进行了一些修改以处理您的情况:
   public static class Factory<C> where C : IBaseClass,new()
    {
        private static object initialData;
        private static Dictionary<IKey,Triple<EventHandlerTypes,int,WeakReference>> handlers = new Dictionary<IKey,WeakReference>>();
        private static Dictionary<IKey,object> data = new Dictionary<IKey,object>();

        static Factory()
        {
            C newClass = new C();
            newClass.RegisterSharedData(registerSharedData);
        }

        public static void Init<IT>(IT initData)
        {
            initialData = initData;
        }

        public static Dt[] GetData<Dt>()
        {
            var dataList = from d in data where d.Key.GetKeyType() == typeof(Dt) select d.Value;

            return dataList.Cast<Dt>().ToArray();
        }

        private static void registerSharedData(IKey key,object value)
        {
            data.Add(key,value);
        }

        public static C Create(int? group)
        {
            C newClass = new C();
            newClass.RegisterSharedHandlers(group,registerSharedHandlers);
            // this is a bit bad here since it will call it on all instances
            // it would be better if you can call this from outside after creating all the classes
            Factory<C>.Call(EventHandlerTypes.SetInitialData,initialData);
            return newClass;
        }

        private static void registerSharedHandlers(IKey subscriber,int? group,EventHandlerTypes type,SharedEventArgs> handler)
        {
            handlers.Add(subscriber,new Triple<EventHandlerTypes,WeakReference>(type,group ?? -1,new WeakReference(handler)));
        }

        public static void Call<N>(EventHandlerTypes type,N data)
        {
            Call<N>(null,type,data);
        }

        public static void Call<N>(object sender,N data)
        {
            lock (handlers)
            {
                var invalid = from h in handlers where h.Value.Third.Target == null select h.Key;

                // delete expired references
                foreach (var inv in invalid.ToList()) handlers.Remove(inv);

                var events = from h in handlers where h.Value.First == type && (!@group.HasValue || h.Value.Second == (int)@group) select h.Value.Third;

                foreach (var ev in events.ToList())
                {
                    // call the handler
                    ((Action<object,SharedEventArgs>)ev.Target)(sender,arg);
                }
            }
        } 
    }
    ,        制作一个包含Dictionary的类。创建或获取此新类的实例将以一致的方式加载字典。然后,您的BO可以使用该类的一个实例,从而确保它们都使用相同的数据(因为包含列表的类知道如何使用适当的数据集进行自身加载)。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res