首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala工厂模式

Scala工厂模式
EN

Stack Overflow用户
提问于 2011-03-11 15:41:10
回答 3查看 1.4K关注 0票数 0

在尝试编写更可测试的Java代码时,我一直在使用Martin几年前在博客中提到的Model模式(http://martinfowler.com/eaaDev/ModelViewPresenter.html --是的,我知道他反对它,但我仍然喜欢简单)。

我为每个JFrame、JDialog等创建一个视图接口,并使用一个工厂来实际生成它们,以便为单元测试生成模拟。

下面是一组小的示例类和接口。在Scala中有比直接语法翻译更好的方法吗?换句话说,我如何使用特征、自类型引用等来更好地遵循枯燥的原则,并且仍然编写类型安全的代码?

代码语言:javascript
复制
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionListener;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JButton;
import javax.swing.JDialog;

interface View {
    void okButtonAddActionListener(final ActionListener actionListener);
}

class Dialog
        extends JDialog
        implements View {
    private final JButton okButton = new JButton("OK");

    public Dialog(final Window owner,
                  final ModalityType modalityType) {
        super(owner, modalityType);
    }

    public void okButtonAddActionListener(final ActionListener actionListener) {
        okButton.addActionListener(actionListener);
    }
}

interface ViewFactory<I, C extends I> {
    I newView(final Window owner,
              final ModalityType modalityType)
            throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException;
}

class AbstractViewFactory<I, C extends I>
        implements ViewFactory<I, C> {
    private final Class<C> cls;

    public AbstractViewFactory(Class<C> cls) {
        this.cls = cls;
    }

    public I newView(final Window owner,
                     final ModalityType modalityType)
            throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        final Constructor<C> constructor = cls.getConstructor(Window.class, ModalityType.class);

        return constructor.newInstance(owner, modalityType);
    }
}

class DialogFactory
        extends AbstractViewFactory<View, Dialog> {
    private static final class InstanceHolder {
        public static ViewFactory<View, Dialog> instance = new DialogFactory();
    }

    public DialogFactory() {
        super(Dialog.class);
    }

    public static ViewFactory<View, Dialog> getInstance() {
        return InstanceHolder.instance;
    }

    public static void setInstance(final ViewFactory<View, Dialog> instance) {
        InstanceHolder.instance = instance;
    }
}

// Here is a typical usage in production
class DialogFactoryUser {
    private void userFactory() {
        final Window window = new Window(null);
        try {
            final View view = DialogFactory.getInstance().newView(window, ModalityType.APPLICATION_MODAL);
        } catch (final Exception ex) {
            ex.printStackTrace();
        }
    }
}

// Here is a typical usage in a unit test
class Test {
    public void test() {
        ...
        mockView = createMock(View.class);
        final Window window = new Window(null);
        mockViewFactory = createMock(ViewFactory.class);
        expect(mockViewFactory.newView(window, ModalityType.APPLICATION_MODAL)).andReturn(mockView);
        ...
        DialogFactory.setInstance(mockViewFactory);
    }
}

更新::我意识到我去年问了一个相似问题,得到了一个不同的“最佳”答案。看看厚脸皮的答案--非常好。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-03-11 16:27:00

我想看看饼型。它通常用于进行完全依赖注入,而不是仅仅抽象出对象构造,但它也可以提供这种功能。基本思想是将应用程序配置捆绑到一个特性中,然后将其混合在一起,生成运行时和测试设置:

代码语言:javascript
复制
trait GUI {
  trait View { /* ... */ }
  def buildView(): View
}
/**
 * Your "real" application
 */
object RealGUI extends GUI {
  def buildView() = newView(/*...*/)
}
/**
 * Your mocked-up test application
 */
object TestGUI extends GUI {
  def buildView() = createMock(classOf[View])
}
票数 3
EN

Stack Overflow用户

发布于 2011-03-11 18:03:13

Lift是通过具有一个通用工厂接口来实现的,该接口具有一个provide: Type(清单) => OptionType函数。它的定义如下(我认为):

代码语言:javascript
复制
trait Factory {
  def provide[T: Manifest]: Option[T]
}
票数 3
EN

Stack Overflow用户

发布于 2011-03-11 16:58:24

除了调用setInstance来使用模拟DialogFactory创建DialogFactory.getInstance之外,您还可以让object Dialog成为创建Dialog的工厂。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5275007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档