1

想知道人们如何在程序中设计对象和使用设计模式。

例如:

假设我有两种类型的汽车(宝马,奔驰)和两种颜色(黑色,白色),但是颜色对象已经存在两种方法,它们是

[Color initWithBlack];
[Color initWithWhite];

在 .h 文件中定义两个方法

- (Car *)makeWithType:(NSString *)type;
- (Car *)makeWithType:(NSString *)type andColor:(NSString *)color;

在 .m 文件中

- (Car *)makeWithType:(NSString *)type
{
    // default is black
    return [self makeWithType:type andColor:@"black"];
}

- (Car *)makeWithType:(NSString *)type andColor:(NSString *)color
{
    Car *car = [[Car alloc] init];
    car.type = type;
    switch(color) {
        case "black":
            [car addColor:[Color initWithBlack]];
            break;
        case "white":
            [car addColor:[Color initWithWhile]];
            break;
        default:
            break;
    }
    return car;
}

它是定义和实现对象的正确方法吗?

是否存在松散或紧密的依赖耦合?

如果很紧,如何改进设计以减少耦合?

4

2 回答 2

2

在我看来,这是一个典型的工厂模式,你有一个为你创建对象的对象/类。在这种情况下,我可以调用它CarsFactory,方法可以是类方法 (+) 而不是实例方法 (-),所以:

+ (Car *)makeWithType:(NSString *)type;
+ (Car *)makeWithType:(NSString *)type andColor:(NSString *)color;

您还可以看看Apple 如何在他们自己的课程中应用它。这也是Jon Reid 的一篇有趣的文章

于 2013-11-08T09:06:12.943 回答
1

假设汽车类型本身对汽车类别没有任何影响,那么您所拥有的将是正确的。

那里有一些缺陷,首先,- (Car *)makeWithType:(NSString *)type;方法应该是类方法而不是实例方法。让它成为一个实例方法就违背了它的目的,因为需要初始化一辆虚拟汽车,然后通过它创建正确的汽车。

此外,如果您在某个时候发现 BMW 可以具有 Benz 所没有的属性,那么子类化会更合适。请注意,您仍然可以保留类似的类方法来创建汽车,但在其中确定正确的子类并返回该类的实例。这就是他们所说的类集群。例如 UIButton 是一个类簇,它接受一个类型并为给定类型返回一个合适的具体子类。

更多的东西,如果你有常量,比如汽车品牌或颜色,那么除非颜色对象做了什么,那么你最好使用枚举而不是字符串和对象。这样做有几个优点,首先是清晰,现在在查看 Car 头文件时不了解可用的类型/颜色。使用枚举,您可以立即看到可用的值。其次是正确性,使用字符串很容易出错,并且编译器不会检查正确性,使用枚举如果你使用了一个未定义的值,你会得到一个很大的红色警报。

因此,作为结论,这是我将用于类 Car 的标题(假设 BMW 和 Benz 只是类型并且没有为汽车添加特殊含义)

typedef NS_ENUM(NSUInteger, CarMake) {
    CarMakeBMW,
    CarMakeBenz,
};

typedef NS_ENUM(NSUInteger, CarColor) {
    CarColorBlack,
    CarColorWhite,
};

@interface Car : NSObject

+ (Car *)makeWithType:(CarMake)make;
+ (Car *)makeWithType:(CarMake)make andColor:(CarColor)color;

@end

如果您确实需要使用 Color 对象(顺便说一句,请注意initWithWhi(t)e方法名称中有错字),那么您应该将该颜色传递给该方法,而不是引用该颜色的字符串。或者,通过基于传入的枚举值在类方法中创建合适的对象,混合使用我上面的标题和颜色对象。

于 2013-11-08T09:14:39.483 回答