3

背景:我有一个大型(几百行)类,它管理基于一些原始类型数据结构的概念

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
    //...
}

问题是如果一个文件中有太多不相关的辅助方法,可读性并没有提高。

这个问题的答案让我大部分时间都在那里。我可以在同一个包中,在它们自己的类中声明结构,并访问原始成员字段或调用相关方法。但我仍然想知道这里公认的智慧,因为这个组织并不容易想到。

您是否曾经将update()build()函数放在他们自己的文件中?如果是这样,他们的共同任务应该在哪里声明?

4

4 回答 4

5

我强烈推荐阅读Martin Fowler 的Refactoring亚马逊链接);它应该在每个程序员的库中,并且可以帮助您解决这种情况。我会在帖子中提及。

如果一个类有太多代码,那么通常是时候拆分这个类了。这可能需要创建具有类的成员变量(委托功能),或者可能意味着动态创建一个对象(将方法替换为方法对象)。有共同点的事物是应用继承或状态/策略模式的好例子。

简短的回答

是的,您甚至可以将这些功能放在自己的文件中。但是,我会改为让他们上课。也许UpdaterBuilder对象。您可以继承自BuilderCommonUpdaterCommon类。这些新对象将与旧对象耦合,但这没关系。您可以考虑将这些新的类集放在它们自己的包中。分层组织将有助于提高通用代码的可读性和重用性。尝试利用继承等概念和泛型等抽象技术来为您完成工作。如果你能找到 、 等之间的共同点doAdoB就用它们制作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 {...}

绝对用对象替换那些数组并添加一个接口。

结束

根据我的经验,通常只需要定期应用其中一些概念,就可以显着提高代码质量。如果一个包、类、方法、条件等变得不守规矩,把它分解成一个更小的单元。继续将细节功能下放到非常小的方法中,以便您可以从高层次查看代码。

于 2013-09-14T22:57:28.853 回答
1

编写同一段代码有许多不同的方法。我喜欢把我的代码写成一种我可以用实际语言解释它的方式。

例如,假设我正在创建一个人。如果我将所有身体部位放在一个类中,阅读起来会有点混乱。

我可以将 Head、Limbs 和 Torso 放入单独的类中,然后将它们全部放入我的 Human 类中,但即便如此,这些身体部位中的每一个都非常复杂。你可能想再分解一下。

我可以为眼睛、鼻子、嘴巴和耳朵创建一个类,然后在你的头类中引用它们。

手指、手指关节、指甲……所有这些都可以进入手类。

这完全取决于你的心态。构建完所有类后,您可以根据自己的喜好引用它们。

为了继续这个例子,至少对我来说,我会在 Arm 类中引用 Hand 类,因为每个手臂都包含一只手(希望......)

如果我跟注,它看起来像这样:

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()

这只是我个人的看法。并不是说这是正确的方法,但老实说,真的没有正确的方法,看看事情可以通过多种方式完成。尽可能寻求效率总是好的,但你不想使用你也不理解的代码

于 2013-09-15T00:25:19.180 回答
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 */}

这将提供松散耦合,并且代码之间更容易分离,因此当您想要修改任何内容时,您不会转到您的客户端类,而是会转到这部分的实现类,而您的原始客户端类保持不变

并且正如 OO 原则所要求的那样......在您的代码中依赖最少,它将获得更大的灵活性,当您在代码中找到“新”这个词时,它就会变得越不灵活,请注意例如在 Client 类中,几乎没有“new”关键字,这意味着它非常灵活,易于维护

于 2013-09-15T01:06:13.587 回答
-1

这个问题的另一个解决方案是模板方法模式。

于 2013-10-01T19:32:36.137 回答