需要一些关于iOS项目的面向对象设计的建议

时间:2012-10-03 06:33:39

标签: ios iphone objective-c

我对代码设计有几个问题。这可能很长。我会尽可能地缩短它。

Q1)依赖还是独立?

创建一个类并添加所需的功能,以便允许对象更改自己的状态与状态由控制器(也称为viewcontroller)更改

我发现代码示例在尝试沟通时最好: 注意:我减少了一些代码行。来自http://www.techotopia.com/index.php/An_Overview_of_Objective-C_Object_Oriented_Programming的原始代码。

无论如何,如果我必须为帐户设置帐户余额,建议我这样做:

@interface BankAccount: NSObject
{
    double accountBalance;
    long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
@end

// Implementation Section Starts Here

@implementation BankAccount

-(void) setAccountBalance: (double) x
{
    accountBalance = x;
}

-(double) getAccountBalance
{
    return accountBalance;
}
@end

//usage
    BankAccount *account1 = [BankAccount alloc] init];

    [account1 setAccountBalance: 1500.53];

----但是我相信我会把它写在这样的控制器中:------

@interface BankAccount: NSObject
{
    double accountBalance;
    long accountNumber;
}

import "BankAccount.h"
@interface MeViewController : UIViewController 
-(void)setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc;
@end

@implementation myViewController

-(void) setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc
{
    tempBankAcc.accountBalance = x;
}

//USAGE
BankAccount *account1 = [BankAccount alloc] init];

[self setAccountBalance(Account1,1500.53)]

@end

因为我认为是我(meViewController)设置AccountBalance,而不是帐户本身,因为帐户只是一个帐户。 这是一个非常糟糕的主意吗?我可以通过他们的例子看到该对象可以自我管理(独立)意味着改变自己的状态,而我的方法说BankAccount只能通过/与控制器(依赖)修改 ???

Q2)控制器应该/不应该是什么?

我还在某处读过控制器内部写的代码应仅用于:

响应用户互动&更新视图

这意味着我不应该在控制器中执行以下操作:

与NSUserDefaults进行读取或写入。由于它是一个单例,我认为无论哪个控制器当前处于活动状态,写入它都会更容易?馊主意? 我知道我应该在applicationDidEnterBackground和applicationWillTerminate中保存数据(包括NSUserDefaults),所以这是一个不好的想法,以保存在其他地方(例如在另一个控制器中)。

Q3)您最常使用哪种设计模式,哪些设计模式错误地滥用?

单身: 我的理解是[UIApplication sharedApplication],[NSNotification defaultCenter]和其他单例可以通过所有控制器访问,NSObject子类怎么样?或UIView子类?

显然,当模型更新时,您可以使用NSNotification通知其他控制器。 有人可以告诉我何时使用以及如何使用它的示例? 也许当您导入一些具有与最初预期不同的属性的数据时,可以向观察者通知升级的数据模型,这是您在数据模型中何时通知控制器的示例?

现在有足够的问题。

很抱歉,但我不得不把它们全部搞定: - )

4 个答案:

答案 0 :(得分:2)

首先要做的事情:不要使用这个

@interface BankAccount: NSObject
{
    double accountBalance;
    long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
@end

在这里,accountBalance ivar是公开的,而它应该是私有的。

相反,请使用@property

@interface BankAccount: NSObject
    @property (assign, nonatomic) double accountBalance;
@end

那将定义一个setter:

- (void)setAccountBalance:(double)accountBalance { ... }

和一个吸气者:

- (double)accountBalance { ... }

以及名为_accountBalance私有实例变量(ivar)。

然后,您可以在实施中使用:

@synthesize accountBalance;

会自动创建这样的setter / getter:

- (void)setAccountBalance:(double)accountBalance {
    _accountBalance = accountBalance;
}

- (double)accountBalance {
    return _accountBalance;
}

答案 1 :(得分:1)

Q1)模型层对象,特别是那些将与之交互和变异的对象,应该对自己的内部表示负责,并代表交互规则的知识。对于银行账户,我认为您提出的两种方法都是错误的。第二个特别是因为它实际上甚至负责更新状态远离帐户。但第一个也是因为它只提供setBalance方法,这在现实世界中没有意义。使用该账户的人现在必须处理转账,取款,存款,利息等所有逻辑。实际上,银行帐户应该有方法deposit withdraw balance等等,这样它就可以代表这些互动发生的规则和逻辑。在这种情况下,借鉴它在现实生活中的运作方式可能会有所帮助。

Q2)很多这取决于你的应用程序的设置方式。一个简单的应用程序模型层可能只是一个plist或NSUserDefaults和一些NSDictionary实例。在这种情况下,您可能不希望视图控制器与之交互,但可能是数据控制器对象。但是你可以让视图控制器与那种模型交谈。当事情变得更复杂时,你肯定需要分离关注点,让控制器对象更接近数据模型,或者拥有更复杂的模型来提供交互规则。就个人而言,我要避免让所有的视图控制器加载NSUserDefaults,你可以只创建一个可以处理它的数据控制器类并根据需要实例化它。

Q3)我在这里看到两个问题。不确定“所有控制器都可访问”的含义。但是当正确使用时,NSNotification非常有用。假设您有3个视图控制器,所有视图控制器都协调银行帐户的不同视图 - 一个是分类帐,一个是饼图,一个是预算计算器。当应用程序请求从互联网刷新银行帐户的信息时,当该请求返回时,它可以立即通知所有这三个视图控制器,并且他们可以相应地刷新他们的视图。只要你有多个对象有兴趣知道发生了什么事情,它就会被用到。

希望这有帮助,如果您有任何问题,请与我联系。

答案 2 :(得分:1)

<强> Q1 如果从对象本身中删除所有业务逻辑,它只不过是一个浅容器对象。此外,您需要在您使用的每个控制器中复制该逻辑。业务逻辑进入业务对象。

对于您的具体示例,控制器的方法什么也不做,只是将调用委托给对象本身(事实上,如果您在此处使用属性,则调用相同的方法)。所以你一无所获。在控制器中使用该方法可能没什么问题,如果控制器做的不仅仅是调用对象,可能会更新更多的数据。这里的一个好提示是控制器不使用任何自己的实例变量。它很容易成为一种类方法。这是代码味道。

<强> Q2 基本上,您有三种选择来访问NSUserDefaults:应用程序级别,视图控制器级别或视图级别。

最糟糕的情况是视图级别 - 视图应该在任何上下文中工作,并且应该以您喜欢的任何方式进行配置,并且它当然不应该依赖于某些神奇的外部事物。这将使可重用性(不仅对于其他应用程序,而且在同一个应用程序中)成为一种痛苦。

访问视图控制器级别的默认值通常是可以的,特别是如果他们采取一些单例角色。即如果您只有一个播放屏幕和一个设置屏幕,则每个屏幕都可以轻松与默认值对话。如果你可能有不同配置的同一个类的几个实例,那么就会产生一种痛苦和难闻的工作来“个性化”这些实例。

这是您希望在视图控制器之外放置默认访问权限的地方,这是最优雅和最灵活的方法,但有时并非必要。

可重用性可能比预期更早,即打开第二个文本编辑器窗口(可能显示或不显示不同的字体),第二个设置屏幕(即弹出框),第二个用于棋盘游戏的播放屏幕等。

<强> Q3 我认为单身人士本身并不好。不过,它们确实带有高昂的价格。它们在早期阶段很方便,就像全局变量一样。

很快就会变得非常昂贵。没有所有权,一切都是共享的,没有机会改变一个位而不影响该对象的其他用户。依赖于单身的物体的可重用性很差,因为你总是需要那些单身人士。我倾向于在大多数时候避开它们。每当我在我的代码中使用其中一个时,摆脱它们是一个很好的决定。

至于通知:它们实际上是为在系统级别进行通信而设计的。它们不应该被滥用于正常的应用逻辑和通信。这是系统级事件的广播。如果你用它们作为对象通信的替代品,这是一个可靠的地狱方式。这会将的每个逻辑从代码中删除,并且无法构建负责任的代码。

答案 3 :(得分:0)

阅读斯坦福关于MVC的讲座。我想你会在那里找到很多答案http://www.stanford.edu/class/cs193p/cgi-bin/drupal/node/205