【问题标题】:Abstract Factory method pattern抽象工厂方法模式
【发布时间】:2016-07-12 13:18:26
【问题描述】:

我在网上浏览了几个视频和博客。感觉好像我什么都懂,但是仍然在努力实现抽象工厂模式。这是我的要求:

  1. 我有一个用户类,它应该提供一个用户对象。
  2. 我的应用程序中有两种类型的用户,例如服务提供者 (Provider) 和服务接收者 (Consumer)。
  3. 这两种类型的用户之间有一些共同的属性,例如姓名、电子邮件 ID、手机号码等。对于 Provider 类型,会有一些额外的属性。
  4. 提供者类型可以是例如出租车司机或餐厅等

我想为这个用户类实现抽象工厂和工厂方法模式,以便应用程序可以与用户模型分离,并且每当应用程序需要提供者或消费者类型的用户时,它应该得到正确的对象。

到目前为止我尝试了什么:

AbstractUserProtocol.h

@protocol AbstractUserProtocol

@required
@property(nonatomic, strong) id delegate;
@property(nonatomic, readonly, getter=isExist) BOOL exist;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *emailID;
@property (nonatomic, assign) NSInteger phoneNumber;

-(void)saveUserData;

-(void)retrievUserData;

@end

AbstractUser.h

@interface AbstractUser : NSObject <AbstractUserProtocol>

-(id)initWithType:(UserType)usrType;

@end

AbstractUser.m

@implementation AbstractUser
@synthesize delegate, exist, name, emailID, phoneNumber;

-(id)initWithType:(UserType)usrType
{
    self = nil;
    if (usrType == kConsumer) {
        self = [Consumer alloc]init];
    }
    else if (usrType == kProvider) {
        self = [ProviderFactory alloc] initWithServiceType:TaxiService];
    }

    return self;
}

-(void)saveUserData {
    [NSException raise:NSInternalInconsistencyException
             format:@"You have not implemented %@ in %@",
 NSStringFromSelector(_cmd), NSStringFromClass([self class])];
}

-(void)retrievUserData {

}

@end

现在从 AbstractUser 类创建了两个子类 Consumer 和 ProviderFactory。

消费者.h

@interface Consumer : AbstractUser
@property (nonatomic, strong) NSString *address;
@end

ProviderFactory.h

@interface ProviderFactory : AbstractUser
-(id)initWithServiceType:(ServiceType)srvType;
@property(nonatomic, strong) NSString *ownerDetails;

@end

因此,如果将来我的应用程序想要支持其他业务用户,例如 Taxi 和 Restaurant 类型,那么我只需要创建一个类并通过 ProviderFactory 类进行初始化。

我的方法对于抽象工厂模式是否正确?感谢任何指导。

【问题讨论】:

    标签: ios objective-c oop design-patterns


    【解决方案1】:

    根据您的后续问题,我编辑了答案。

    我不完全确定您是否需要使用 AbstractFactory 来完成您想要完成的任务。 AbstractFactory 的基础是它允许你

    提供一个接口来创建相关或依赖的家庭 没有指定具体类的对象(Gamma 等人)

    以 Gamma 等人的 Design Patterns: Elements of Reusable Object-Oriented Software 为例。假设您正在创建一个工具包来为文档编辑器构建用户界面。您可能有一堆小部件对象,如滚动条、按钮、工具栏等。但您可能希望稍后为文档编辑器添加不同的外观。因此,您可以使用AbstractFactory 提供一个接口来创建所有小部件产品(即createScrollbarcreateButtons 等),但是要更改外观,您可以继承抽象类并覆盖比如说,createScrollbar 返回一个具有 3-D 效果的滚动条的方法。在另一种情况下,您将抽象类子类化以创建粉红色滚动条。选项是无穷无尽的,并且由于您的客户端代码并不关心滚动条的外观(所有客户端关心的是它是否滚动文本),您可以轻松添加未来的外观而无需接触客户端代码。

    在你的情况下,客户关心它会得到什么样的AbstractUser,因为在某些情况下它需要Customer,在某些情况下需要Provider。因此,无论哪种方式,如果将来您添加了一种新的用户,您的客户端代码就必须更改。

    也就是说,我认为对您来说最好的方法是创建一个抽象的 User 基类,然后将其子类化并将特定于用户的属性添加到子类中。这是我的意思的一个例子。

    AbstractUser.h

    #import <Foundation/Foundation.h>
    
    @interface AbstractUser : NSObject
    
    @property(nonatomic, strong) id delegate;
    @property(nonatomic, readonly, getter=isExist) BOOL exist;
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, strong) NSString *emailID;
    @property (nonatomic, assign) NSInteger phoneNumber;
    
    @end
    

    消费者.h

    #import "AbstractUser.h"
    
    @interface Consumer : AbstractUser
    
    @property (strong, nonatomic) NSString *address;
    
    @end
    

    ViewController.m

    #import "ViewController.h"
    #import "Consumer.h"
    #import "Provider.h"
    
    @interface ViewController ()
    
    @property (strong, nonatomic) Consumer *consumer;
    @property (strong, nonatomic) Provider *provider;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
    
        [super viewDidLoad];
    
        _consumer = [[Consumer alloc] init];
        _provider = [[Provider alloc] init];
    
        self.consumer.name = @"Jason";
        self.consumer.address = @"some address";
    
        self.provider.name = @"Stack Overflow";
    
    @end
    

    【讨论】:

    • 根据我上面的实现,如果我要求 AbstractUser 创建一个 Consumer 类型的用户,那么返回给我的对象只能通过 AbstractUserProtocol.h 访问抽象类已知的属性(名称、emial 等)但不是“地址”属性。例如consumberObj.address 是不可能的,因为 consumerObj.name/email 是可能的。客户端应用如何访问 consumerObj.address?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    相关资源
    最近更新 更多