2

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

Q1) 依赖还是独立?

创建一个类并添加所需的功能,以允许对象更改自己的状态与控制器(又名视图控制器)更改的状态

我发现代码示例在尝试交流时是最好的: 注意:我减少了一些代码行。来自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

4 回答 4

2

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

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

在这里,accountBalanceivar 是公共的,而它应该是私有的。

相反,使用@property

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

这将定义一个二传手:

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

和一个吸气剂:

- (double)accountBalance { ... }

和一个名为_accountBalance.

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

@synthesize accountBalance;

它将像这样自动创建setter/getter:

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

- (double)accountBalance {
    return _accountBalance;
}
于 2012-10-03T06:55:19.527 回答
1

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

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

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

希望这会有所帮助,如果您有任何问题,请告诉我。

于 2012-10-03T07:08:17.323 回答
1

Q1 如果把对象本身的所有业务逻辑都拿掉,无非就是一个浅容器对象。此外,您需要在您使用的每个控制器中复制该逻辑。业务逻辑进入业务对象。

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

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

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

访问视图控制器级别的默认值通常是可以的,尤其是当它们扮演一些单例角色时。即,如果您只有一个播放屏幕和一个设置屏幕,则它们中的每一个都可能很容易与默认值对话。如果您有可能对同一类的多个实例进行了不同的配置,那么将这些实例“个性化”会很痛苦,而且气味难闻。

这是您希望将默认值的访问置于视图控制器之外的地方,这是最优雅和灵活的方法,但有时只是没有必要。

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

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

它们很快就会变得非常昂贵。没有所有权,一切都是共享的,没有机会在不影响该对象的其他用户的情况下进行任何更改。依赖于单例的对象的可重用性很差,因为您也总是需要这些单例。大多数时候我倾向于避开它们。每当我的代码中有其中一个时,摆脱它们都是一个不错的决定。

至于通知:它们实际上是为在系统级别进行通信而设计的。它们不应该被滥用于正常的应用程序逻辑和通信。这是系统级事件的广播。如果您将它们用作对象通信的替代品,那么这无疑是一条通往地狱的道路。这会将所有逻辑都从代码中剔除,并且无法构建负责任的代码。

于 2012-10-03T07:47:26.080 回答
0

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

于 2012-10-03T06:56:41.760 回答