Java 必须将上下文传递给大多数类是糟糕设计的标志吗?

Java 必须将上下文传递给大多数类是糟糕设计的标志吗?,java,android,oop,Java,Android,Oop,Android的设计方式是,为了让一个方法读取一个资源,它必须能够访问一个数据库 由于我的应用程序中的大多数类依赖于字符串资源的灵活性(例如,在不必更改代码的情况下更改语言等),因此我的简单解决方案是在它们的构造函数中传递一个上下文,以提供对每个此类类的资源访问 对我来说,在构造函数中只传递一个字符串是没有意义的,因为类需要灵活地访问不同数量的字符串 所以,为了简化事情,我只传递,每当需要字符串资源时,我只使用 这是设计不好的迹象吗 有没有更好的方法来实现这一点?这是一个-您传递一个服务定位器(

Android的设计方式是,为了让一个方法读取一个资源,它必须能够访问一个数据库

由于我的应用程序中的大多数类依赖于字符串资源的灵活性(例如,在不必更改代码的情况下更改语言等),因此我的简单解决方案是在它们的构造函数中传递一个上下文,以提供对每个此类类的资源访问

对我来说,在构造函数中只传递一个字符串是没有意义的,因为类需要灵活地访问不同数量的字符串

所以,为了简化事情,我只传递,每当需要字符串资源时,我只使用

这是设计不好的迹象吗

有没有更好的方法来实现这一点?

这是一个-您传递一个服务定位器(通常称为“上下文”)并从中获取所需的依赖项。这不是一个反模式,也不是一个坏的设计,但通常被认为是优越的


您正在做的是——将服务定位器进一步向下传递到对象图中。建议只给每个类它所需要的依赖项。因此,不是在构造函数中传递
上下文
,而是传递它所需的所有字符串。这样您就不会违反

这是一种罕见的情况,在这种情况下,全局可访问类可能比将
上下文
传递给每个类更好

我会考虑创建一个用于本地化的单子,然后在里面使用<代码>上下文<代码>(除非您需要在所有地方都使用<代码>上下文< /代码>)。


当然,这是一个品味和偏好的问题。YMMV

定期发送上下文作为参数并记住它们是危险的,请阅读以下内容:


更好的方法是将应用程序子类化,并使用它生成singleton(应用程序对象也是上下文)。这种解决方案没有明显的缺点。

我不知道这样使用它是否是一种不好的做法,但我做了时间比较,将200个轻量级对象加载到数组列表中,其中一个构造函数将上下文作为参数,另一个构造函数通过@Eric Farr建议的静态方法获得所需的上下文。最终的结果是,通过静态方法而不是传递给构造函数来访问上下文总是快5-25%

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    initBlocks(map); // takes context through static method
    blocks.clear();
    initBlocks(getContext(), map); // pass context down to every block object
    mainthread = new GameThread(getHolder(), this);
    mainthread.setRunning(true);
    mainthread.start();
}


I/art: Background sticky concurrent mark sweep GC freed 1070(51KB) AllocSpace 
objects, 44(3MB) LOS objects, 27% free, 8MB/11MB, paused 27.450ms total 132.688ms
I/art: Background partial concurrent mark sweep GC freed 1638(66KB) AllocSpace 
objects, 36(3MB) LOS objects, 29% free, 9MB/13MB, paused 13.982ms total 184.900ms
I/art: Background sticky concurrent mark sweep GC freed 916(44KB) AllocSpace objects, 
37(3MB) LOS objects, 16% free, 11MB/13MB, paused 17.710ms total 127.963ms
**I/System.out: TIME IT TOOK TO PROCESS >> 2254155160**
I/art: Background partial concurrent mark sweep GC freed 1780(77KB) AllocSpace 
objects, 208(8MB) LOS objects, 38% free, 6MB/10MB, paused 22.850ms total 193.625ms
I/art: WaitForGcToComplete blocked for 5.262ms for cause Background
I/art: Background sticky concurrent mark sweep GC freed 959(46KB) AllocSpace objects, 
39(3MB) LOS objects, 24% free, 7MB/10MB, paused 15.160ms total 101.055ms
I/art: Background partial concurrent mark sweep GC freed 1873(71KB) AllocSpace 
objects, 32(2MB) LOS objects, 32% free, 8MB/12MB, paused 17.253ms total 154.302ms
I/art: Background sticky concurrent mark sweep GC freed 888(42KB) AllocSpace objects, 
36(3MB) LOS objects, 17% free, 10MB/12MB, paused 42.191ms total 179.613ms
I/art: Background partial concurrent mark sweep GC freed 1243(50KB) AllocSpace 
objects, 30(2MB) LOS objects, 27% free, 10MB/14MB, paused 29.423ms total 283.968ms
**I/System.out: TIME IT TOOK TO PROCESS >> 3079467060**
I/art: Background sticky concurrent mark sweep GC freed 343(16KB) AllocSpace objects, 
14(1232KB) LOS objects, 0% free, 21MB/21MB, paused 20.481ms total 162.576ms
I/art: Background partial concurrent mark sweep GC freed 396(13KB) AllocSpace 
objects, 4(280KB) LOS objects, 15% free, 21MB/25MB, paused 21.971ms total 243.764ms
I/art: Background sticky concurrent mark sweep GC freed 471(166KB) AllocSpace 
objects, 0(0B) LOS objects, 0% free, 37MB/37MB, paused 26.350ms total 133.655ms
I/art: Background partial concurrent mark sweep GC freed 356(10KB) AllocSpace 
objects, 1(10MB) LOS objects, 12% free, 27MB/31MB, paused 41.909ms total 299.517ms

我不知道你的情况,但我会提高性能(y)。

它确实感觉有点凌乱,不是吗…@jondavidjohn每一个设计都是某种妥协的结果。我不喜欢第一次看到Android时那种背景传递API@Bozho更糟糕的是:包名在运行时是完全静态的,然而,它需要上下文来理解:我不同意,我认为设计是按照它的意图进行的。
上下文有时很难跟踪,但它迫使开发人员进行更好的设计。当你发表评论时,至少要有建设性,并添加一些理由。这与@Eric Farr的建议是一致的+1.无需使用单例进行本地化。如果你使用上下文对象,Android会为你做。为什么要用做同样事情的单身汉来重新发明轮子?@Austin Mahoney请解释一下“Android是如何为你做的”?我倾向于接受Eric Farr的答案,只需在Activity.OnCreate()中初始化一个静态上下文成员,因为它极大地简化了实现。您有更好的建议吗?
Context
已经具备OP所需的本地化功能,为什么要将其包装在一个单例中?在
onCreate()
中初始化静态上下文成员是什么意思。如何初始化成员,是否调用
getApplicationContext()
?@austin Mahoney是的。首先,声明
公共静态上下文appContext。第二,在onCreate()中初始化它:
if(appContext==null)appContext=getApplicationContext()。这使它可用于项目中的所有类。。。有什么问题吗?像这样的讨论需要根据SO政策转移到聊天室。如果你需要解释我的评论,请告诉我。我不同意。在这种情况下,亲吻(保持简单)是更好的原则。@Bozho-应用程序作为singleton,你不会通过任何东西,而且更简单。实际上,在任何情况下它都更简单,因为如果您传递任何字符串,您应该知道另一个对象使用的字符串。如果使用上下文,则不必关心对象需要多少字符串和哪些字符串。这就是OOP。当你需要对整个事情进行单元测试时,你就开始模拟“整个世界”:)好吧,我最不希望听到的是数据封装不好,会导致“模拟整个世界”。我之前的评论是关于数据封装的。一个对象用来向用户显示消息的字符串是它自己的东西,仅仅因为它们在资源中,就把它们作为参数从其他人那里发送是不好的做法。从程序员的角度来看,这些字符串属于使用它们的对象,而不是它的调用者。调用者不需要知道这些事情,否则程序员很快就会完全沉浸在代码中。