背景:我有一个很大的(几百行)类来管理基于某些原始类型数据结构的概念
long[] slist; //list of unique patterns (related to polyominoes)
int[][][] sref;//patterns at each place [location][depth][<list of indices in slist>]
问题:填充和更新这些数据的两种方法将会很长,少数5-20行任务,一些是共享的,另一些是唯一的。我可能想为每个子任务创建一个辅助方法。
update(...){
//do A
//do B
//do C
//...
}
build(){
//do D
//do B
//do E
//...
}
问题是如果一个文件中有太多无关的辅助方法,则可读性不会提高。
this question的答案让我大部分都在那里。我可以在它们自己的类中声明相同包中的结构,并访问原始成员字段或调用相关方法。但我仍然想知道这里接受的智慧,因为这个组织并不容易想到。
您是否会将update()
和build()
函数放在自己的文件中?如果是这样,他们的共同任务应该在哪里宣布?
答案 0 :(得分:3)
我强烈建议您阅读Martin Fowler撰写的Refactoring(Amazon link);它应该在每个程序员的库中,并将帮助您处理这样的情况。我将在帖子中提到它。
如果一个类的代码太多,那么通常是分开该类的时候了。这可能需要创建具有类(委派功能)的成员变量,或者它可能意味着动态创建对象(replace method with method object)。共享共性的事情是应用继承或state/strategy pattern的好例子。
是的,您可以将这些功能放在自己的文件中。但是,我会改为让他们上课。可能是Updater
和Builder
个对象。您可以继承BuilderCommon
和UpdaterCommon
类。这些新对象将耦合到旧对象,但这没关系。您可以考虑将这些新类集合放在自己的包中。分层组织将有助于可读性和公共代码的重用。
尝试利用继承和抽象技术(如泛型)等概念为您完成工作。如果您可以找到doA
,doB
等之间的共性,请在其中创建UpdateHelper
个类并将它们放入列表中。然后简单地遍历列表。
这只是中的一个的许多方法:
public class Updater
{
public Updater(List<IUpdateHelper> helpers)
{
helpers = new ArrayList<UpdateHelper>();
this.helpers.add(helpers);
}
public void update()
{
for (IUpdateHelper helper : helpers)
{
helper.performHelp();
}
}
protected List<IUpdateHelper> helpers;
}
public class UpdaterCommon extends Updater
{
public UpdaterCommon()
{
helpers.add(new UpdateHelperA());
... // Etc.
}
}
/*
* This uses inheritance for common helpers, but it could just as well use
* delegation. Also, this assumes that order of invocation for each helper
* doesn't matter.
*/
public class UpdaterOne extends UpdaterCommon {...}
interface IUpdateHelper
{
public void performHelp();
}
public class UpdateHelperA implements IUpdateHelper {...}
绝对replace those arrays with objects并添加界面。
根据我的经验,通常只需要定期应用其中一些概念就可以在代码质量上产生显着差异。如果包,类,方法,条件等变得不守规矩,则将其分解为更小的单元。继续将细节功能推向非常小的方法,以便您可以从高级别查看代码。
答案 1 :(得分:1)
编写同一段代码有很多种不同的方法。 我喜欢把我的代码编写成一种我可以用实际解释它的方式。
例如,假设我正在创建一个人。 如果我将所有身体部位放在一个班级中,那么阅读会有点混乱。
我可以将Head,Limbs和Torso分成几个单独的类,然后将它们全部放入我的Human类中,但即便如此,每个身体部位都非常复杂。你可能想把它分解一下。
我可以为眼睛,鼻子,嘴巴和耳朵上课,然后在你的班主任课程中引用它们。
手指,手指关节,指甲......所有这些都可以进入Hand类。
这完全取决于你的思维方式。一旦您构建了所有类,您就可以引用它们,但这符合您的偏好。
继续这个例子,至少对我来说,我会在Arm类中引用Hand类,因为每个arm都包含一只手(希望......)
如果我要打电话,看起来像这样:
Arm leftArm = new Arm();
Arm rightArm = new Arm();
leftArm.hand.makeFist();
rightArm.hand.raiseMiddleFinger();
尽管将它写出来是非常繁琐的(如果你想要参考手,你必须通过手臂才能找到它),这就是为什么我喜欢使用静态值和返回方法。这都是关于你如何看待编程的。我喜欢将编程与现实世界进行比较。
对于辅助方法,我喜欢将它们视为动作。 如果你想做某些事情,比如'turnOnTv'或'tossBall',那么你会想把这个方法放在备受尊重的类中。
例如,假设您想让某人投球。 你会想要在你拥有用户信息的类中使用'public void tossBall()'方法,所以当你调用它时,它看起来有点像
Person personNumberOne = new Person();
personNumberOne.tossBall()
这只是我个人的意见。不是说这是做这件事的正确方法,但老实说,确实没有正确的方法,看看事情可以通过多种方式完成。在任何地方寻找效率总是好的,但你不想使用你不懂的代码
答案 2 :(得分:1)
这里可能有用的设计模式是抽象工厂模式,您可以在其中创建抽象类/接口,在其中定义您的帮助器方法(作为抽象),并在原始update()和build()中使用此接口方法
并为您的抽象工厂(类/接口)创建一个子类,并在此子类中完成所有工作
你可以将参数传递给你将在你将创建的子类中实现它们时使用的抽象方法,以便保持彼此连接,但是松散耦合
例如:
class Client {
private AbstractFactory factory = null;
public Client(AbstractFactory factory){
this.factory = factory;
}
void update(){
String a = factory.getA();
MyObject b = factory.getB(a);
b.doSomeStuff();
int c = factory.getC(b);
}
void build(){
AnotherObject d = factory.getD();
d.doMoreStuff();
}
}
public interface AbstractFactory{
String getA();
MyObject getB(String a);
int getC(MyObject b);
AnotherObject getD();
}
public class Helper implements AbstractFactory{
// implement your methods here
}
public class MyObject{ /*some helper methods here as well */}
public class AnotherObject{ /*another helper methods here as well */}
这将提供松散耦合,并且更容易在代码之间分离,以便在您想要时 修改任何东西,你不会去你的Client类,相反,将转到这部分的实现类,让原始的Client类保持不变
并且OO原则要求......代码中依赖程度最低,获得的灵活性越大,当您在代码中找到“new”一词时,它的灵活性就越低,请注意客户端例如,类几乎没有“new”关键字,这意味着它非常灵活,易于维护
答案 3 :(得分:-1)
此问题的另一个解决方案是模板方法模式。