Java 重构设计:抽象/接口/无?

Java 重构设计:抽象/接口/无?,java,optimization,interface,refactoring,abstract-class,Java,Optimization,Interface,Refactoring,Abstract Class,首先,请查看我的UI,因为它将帮助您了解问题: 您将了解到,通过选择其中一个,您将得到一组具有相同目标但实施方式不同的类似操作(大多数情况下,登录和注销)。这是一个Android项目(因此是用Java编写的) 这里的主要类是AuthUI。它设置所有的onClickEventListeners,以及单击按钮后要执行的操作。事实上,所有内容都包含在这个类中,但我的小指告诉我,重构代码可能是个好主意,这样我就不会在主类中看到GoogleSignIn和AcclimateSignIn的实际实现(与型号相

首先,请查看我的UI,因为它将帮助您了解问题:

您将了解到,通过选择其中一个,您将得到一组具有相同目标但实施方式不同的类似操作(大多数情况下,
登录
注销
)。这是一个
Android
项目(因此是用
Java
编写的)

这里的主要类是
AuthUI
。它设置所有的
onClickEventListeners
,以及单击按钮后要执行的操作。事实上,所有内容都包含在这个类中,但我的小指告诉我,重构代码可能是个好主意,这样我就不会在主类中看到
GoogleSignIn
AcclimateSignIn
的实际实现(与型号相比,它更能充当控制器

我一直在考虑将
AcclimateAuth
GoogleAuth
设置为与此
AuthUI
类相同的
Authentication
包中的独立类。但是,我想知道解决此问题的最佳方法是什么

我最初的想法是尝试在
AuthUI
中将这两个新类声明为
abstract
extensions
,但后来我想起我只能扩展一个类。因此,第二步我选择了
接口
方法,但决定在实际采取行动之前多想一想

我目前的想法是有一个名为
Auth
的接口,它基本上会设置方法
signIn
signOut
,然后是两个新的
类(
AcclimateAuth
GoogleAuth
)将
实现该接口。
AuthUI
将通过将它们作为
private
属性访问这两个类

但是考虑到我只会有这两个新类的一个实例,也许我应该考虑他们的方法是“代码>静态< /代码>?还是这是一个糟糕的设计选择?

希望得到一些关于在这种情况下什么是好的重构技术的明确答案。

我的想法 我建议使用接口模式

我为什么这么想 它不仅非常适合您的需求,还可以指定一个Auth接口,确保每个实现至少有一些默认方法(默认情况下可能是Signin和Signout方法)。除了有更多的实现之外,它还允许您做的另一件事是,您可以将依赖项注入到主
控制器
类构造函数中。这对可重用性非常有好处,因为如果我想有一个不同的实现,比如说使用其他服务登录,我可以扩展接口并创建我的类。如果不使用接口模式和控制器注入,我将不得不更改主
控制器
类代码,并可能引入bug

如果您不想这样做: 不这样做的最佳情况是让
控制器
类选择它在自己的带有枚举和switch语句的代码中使用的登录实现。例如,google按钮的按钮处理程序会将“登录”枚举设置为G或其他值,然后在“登录”枚举上有一个开关盒,该开关盒将查找G,然后运行google登录实现的代码。这可以作为一个过渡,但如果您有很多实现,它可能会变得混乱/不可读,而且它会引入O(n)时间复杂性,其中包含n个“实现”,因此n个切换情况,以确定您正在使用的实现。构造函数注入使O(1)成为O(1),因为您可以立即获得所需的实现。您还可以使用简单的属性文件设置配置。类似于:“SignInImpl=Google”的内容,作为名为“properties.config”的文本文件中的一行。 然后,您可以使用以下内容加载此属性文件

Properties prop = new Properties();
    try {
        prop.load(YOURCLASSNAMEHERE.class.getResourceAsStream("config.properties"));
然后你的SingInImpl对象可以通过反射变成你需要的任何东西

SignInImpl ImplYouWant = Class.forname(//put the property value here to find your class implementation). 
这甚至更好,因为您可以使用文本文件在运行时指定实现

关于静态方法的话题 如果您只有这些类的一个实例,并且不希望有多个对象四处浮动,那么请务必这样做。它将增加可读性,并允许您更直接地调用方法,而无需实例化对象。这主要取决于您是否真的需要多个实例。代码只是一个示例,可能包含语法错误等

我不推荐抽象类的原因。
当您有很多具体的子类/继承时,抽象类会更好。因为这里没有太多的继承,所以它更多的是容器关系,而不是继承关系。一个很好的类比可能是为动物园建模。如果你想对所有不同类型的动物建模,界面会更好。如果你想描述动物之间的关系,抽象类会更好。您的问题有不同类型的问题作为根本原因,而不是这两个或多个问题之间的关系。

仅仅因为您有一个实例,并不意味着他们的方法应该是静态的。我推荐第二种方法。使用
静态方法的缺点是什么?有趣的答案!请您澄清一下
构造函数的注入
依赖项的注入
是什么意思好吗?如果您的
AuthUI
SignInImpl
对象作为构造函数参数,就是一个例子。这里演示[链接]