重构内部使用相同代码但不同方法的方法
本文关键字:方法 内部 代码 重构 | 更新日期: 2023-09-27 18:28:37
除了一行之外,我有一些方法是相同的(我在对象客户端上调用不同的方法)。我会有更多这样的方法。
除了使用反射之外,还有什么解决方案吗?
private void initClerks(Client client)
{
string[] pks = client.ClerksPKS.Trim(','). Split(',');
foreach (string pk in pks)
{
string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
client.addClerk(JsonConvert.DeserializeObject<Clerk[]>(data)[0]);
}
}
private void initManagers(Client client)
{
string[] pks = client.ManagerPK.Trim(',').Split(',');
foreach (string pk in pks)
{
string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
client.addManager(JsonConvert.DeserializeObject<Manager[]>(data)[0]);
}
}
您可以通过将操作传递到方法中来实现这一点。类似的东西
private void actOnData(Client client, string[] pks, Action<Client, string> addThing)
{
foreach (string pk in pks)
{
string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
addThing(client, data);
}
}
private void initClerks(Client client)
{
string[] pks = client.ClerksPKS.Trim(',').Split(',');
actOnData(client,pks,(c,d) => { c.addClerk(JsonConvert.DeserializeObject<Clerk[]>(d)[0]); });
}
private void initManagers(Client client)
{
string[] pks = client.ManagerPK.Trim(',').Split(',');
actOnData(client, pks, (c, d) => { c.addManager(JsonConvert.DeserializeObject<Manager[]>(d)[0]); });
}
考虑到这不是外部遗留库,我建议重构客户端类以简化其API(我会更改更多内容,但让我们在某个时候停止)
伪代码:
// taking into account Client, manager all are workers
class Client
{
// further whenever you need filter out managers use LINQ OfType<>
List<Workers> workers;
public void Add<T>(T worker) where T: Worker
{
workers.Add(client);
}
}
参见提取方法,
private void Initialize<T>(Client client, string[] pks)
{
foreach (string pk in pks)
{
string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
client.Add(JsonConvert.DeserializeObject<T[]>(data)[0]);
}
}
private void initClerks(Client client)
{
string[] pks = client.ClerksPKS.Trim(',').Split(',');
Initialize<Clerk>(client, pks);
}
private void initManagers(Client client)
{
string[] pks = client.ManagerPK.Trim(',').Split(',');
Initialize<Manager>(client, pks);
}
接下来,两个initClerks/initmanager看起来是多余的,只是对Initialize
的内联调用(当然,如果整个代码库不比这里显示的更复杂的话)
提取方法的典型路径是查找差异并声明相应的方法参数。让我们采用你的initClerks
方法,在里面找到单词Clerk
。其中有3个,一个是Type
,所以我们将制作一个泛型方法,其泛型参数T
对应于Clerk
。映射将类似于
(1) client.ClerksPKS
映射到Func<Client, string>
(2) JsonConvert.DeserializeObject<Clerk[]>
映射到JsonConvert.DeserializeObject<T[]>
(3) client.addClerk
映射到Action<Client, T>
所以常用的方法变成
void Init<T>(Client client, Func<Client, string> getPKS, Action<Client, T> addItem)
{
string[] pks = getPKS(client).Trim(','). Split(',');
foreach (string pk in pks)
{
string data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[Constants.ResponseJson.Data].ToString();
addItem(client, JsonConvert.DeserializeObject<T[]>(data)[0]);
}
}
以及使用
private void initClerks(Client client)
{
Init<Clerk>(client, c => c.ClerksPKS, (c, x) => c.addClerk(x));
}
private void initManagers(Client client)
{
Init<Manager>(client, c => c.ManagerPK, (c, x) => c.addManager(x));
}
创建基类以在其基本Init方法中添加公共逻辑。则在实现BaseClientInitializer的类中重写Insert方法。这种设计模式被称为模板方法。
public abstract class BaseClientInitializer
{
private string[] keys;
public BaseClientInitializer(string[] keys)
{
this.keys = keys;
}
public abstract void Insert(string data);
public void Init()
{
foreach (string pk in keys)
{
var data = JObject.Parse(DBUtils.GetData(Constants.DBProcedures.GetProcedures.GetWorkerDetailsByPkid, pk))[
Constants.ResponseJson.Data].ToString();
this.Insert(data);
}
}
}
public class Clerks : BaseClientInitializer
{
private Client client;
public Clerks(Client client) : base(client.ClerksPKS.Trim(','). Split(','))
{
this.client = client;
}
public override void Insert(string data)
{
client.addClerk(JsonConvert.DeserializeObject<Clerk[]>(data)[0]);
}
}
private void initClerks(Client client)
{
var clerksInitializer = new ClerksInitializer(client);
clerksInitializer.Init();
}
对init管理器执行同样的操作。区别不仅在于插入方法,pks数组也不同:客户端。职员PKS。修剪(',')。拆分(',])-适用于职员和客户。ManagerPK.Trim(',').Split(','')用于经理。所以简单的提取方法不会正确工作。