我正在开发一个带速度计的应用程序,如动画(仪表和箭头表示仪表上的某些东西).我将箭头的位置存储在我的app delegate中声明的全局变量中.我这样做是因为箭头位置被更新并被几个类使用.
但是,我不确定这是一个好的还是坏的设计决定.我的想法是,因为它是一个非关键的信息(只是一个浮动),所以在全局存储时不会造成任何伤害.但每当我对自己说“全球”这个词时,我的OOP心就会受伤.
或者我有单身人士,但据我所知,当开发人员希望创建一个且只有一个特定对象的实例时,会使用单身人士.
我做得对吗还是有更合适的方式做我做的事情?
最佳答案
I am doing it this way because the arrow position is updated and used by several classes.
在许多情况下,您可以缩小范围.这减少了组件间依赖性.
However, I am insecure whether this is a good or a bad design decision. My thoughts are that since it is a non-critical piece of information (just a float), no harm is done when storing it globally. But my OOP heart hurts every time I say the word “global” to myself.
也许您可以将状态(浮动值)移动到车速表中的ivar?例如:您可能只显示一个车速表视图:将它添加到视图模型中更有意义吗?或者也许是它的控制器? (是的,在没有源的情况下提供更具体的示例有点困难)
Alternatively I have studiet singletons, but as far as I have read, singletons are used when the developer wishes to create one and only one instance of a certain object.
没有必要,并且要保持严重的疼痛.我见过的大多数可可单身人士都不应该被认为是单身人士,并且引起了很多麻烦.更好的是,你可以编写使用零单例的程序.这是理想的,易于测试.因此,依赖于app控制器的程序/类型已经受到可测试性和可重用性的影响.
Am I doing it correct or is there a more proper way of doing what I do?
在绝大多数情况下,您可以简单地缩小范围并对其进行本地化,同时删除全局状态.通过更多的努力,您可以将该值作为全局删除 – 这是最好的.
虽然这不是一件好事……让我们假设你真的真的真的必须引入全球状态:
>不要使用单身人士.当你想重用它时,你会重写它很有可能.糖包衣什么是丑陋的.如果你的应用程序控制器由于太多的全局状态而变得一团糟,那么至少你有太多全局状态这一事实将是显而易见的.
>在app控制器中保持全局状态.您的app控制器负责其初始化,生命周期和访问.
>将该状态提供给依赖项,因此它们不会返回(甚至不知道)全局域(app控制器).那么你可以减少影响.
全局状态和应用程序/执行状态之间也存在明显差异.全球国家应该被淘汰.执行状态不是全局状态,而是本地化执行上下文.执行状态可以在适当的级别重新引入,更改,更新,测试和可预测的重用.一个好的设计将在需要时引入执行状态,并在适当的级别同时避免全局状态.
更新
根据OP中的描述,您的样本非常接近我的想象.它提供了一些额外的细节.所以下面的示例(你需要在显而易见的区域中添加一些内容以将它们拼凑在一起)演示了如何更新控制器接口,并且最后有两个免费的“其他”方法,它们进一步说明了如何使用它们:
@interface MONArrowPosition : NSObject
{
float arrowPosition;
}
@end
@implementation MONArrowPosition
- (id)initWithPosition:(float)position
{
self = [super init];
if (nil != self) {
arrowPosition = position;
}
return self;
}
@end
@interface MyViewController1 : UIViewController
{
MONArrowPosition * arrowPosition; // << may actually be held by the model
}
@end
@implementation MyViewController1
- (void)applyRotation
{
[self rotateLayer:arrow from:self.arrowPosition to:callStatus speed:METER_SPEED];
}
@end
@interface MyViewController2 : UIViewController
{
MONArrowPosition * arrowPosition; // << may actually be held by the model
}
@end
@implementation MyViewController2
- (void)viewDidLoad
{
[super viewDidLoad];
/* ... */
[self.slider addTarget:self action:@selector(sliderValueDidChange) forControlEvents:controlEvents];
}
- (void)sliderValueDidChange
{
self.arrowPosition.arrowPosition = self.slider.value;
[self arrowPositionDidChange];
}
@end
/* elsewhere: */
- (void)initializeArrowPosition
{
/* The variable is set to a default of 0.0f */
MONArrowPosition * arrowPosition = [[MONArrowPosition alloc] initWithPosition:0.0f];
/* ... */
}
- (IBAction)someActionWhichPushesMyViewController1
{
// depending on the flow of your app, the body of initializeArrowPosition
// *could* be right here
MyViewController1 * viewController = [[MyViewController1 alloc] initWithNibName:nibName bundle:bundle];
viewController.arrowPosition = self.arrowPosition;
/* push it */
}
然后如果MyViewController1推送MyViewController2,定位和设置箭头位置将很容易.视图控制器也可以在模型中共享一些信息.在您的示例中使用全局,您正在跨越许多实现,这会增加耦合,增加依赖性等.因此,如果您可以采用此方法并本地化执行状态,那么您将有一个良好的开端.那么你可以使用任意数量的MONArrowPositions的任意数量的视图控制器,它们将不受全局状态的影响.再次,我不能使用提供的样本太具体,但我认为这应该说明我最初概述的概念(我不认为需要进行项目范围的审查).