简单工厂/工厂方法/抽象工厂

简单工厂模式
  • 角色划分
    角色一:抽象产品
    角色二:具体产品
    角色三:具体工厂
  • 优点:
    1. 把具体产品的类型从客户端代码中解耦出来,服务器端如果修改了具体的类名,客户端不需要知道。这便符合了面向接口编程的思想。
  • 缺点:
    1. 客户端不得不死记硬背那些常量与具体产品的映射关系。比如说:1对应汉堡包,2对应米线。
    2. 如果具体产品特别多,则简单工厂就会变得十分臃肿,如果有100个产品,switch中就有100个 case。
    3. 最重要的是,变化来了后,客户端需要扩展具体的产品时,势必要修改简单工厂中的源代码,这样便违反了开闭原则。所以变化来时,扩展很不方便。这就引出了工厂方法模式。
简单工厂模式UML图
简单工厂模式UML.png
工厂方法模式(定义)

为了解决简单工厂模式中的缺点,而诞生了工厂方法模式。定义一个用于创建对象的统一的接口,然后由子类实现。

工厂方法模式->角色划分

角色一:抽象产品
角色二:具体产品
角色三:抽象工厂
角色四:具体工厂

UML图
工厂方法模式UML.png
优点:
  • 把具体产品的类型从客户端代码中解耦出来,服务端如果修改了具体的产品类名,客户端不需要知道。
  • 如果具体产品特别多时,解决简单工厂模式变得十分臃肿的问题。
  • 新增业务类时,不需要修改原有的业务类,只需要新增就行,符合开闭原则。


    工厂方法模式 新插入功能类.png
缺点:
  • 如果有多个产品等级或者有产品簇,那么工厂类的数量就会爆炸式增长。
杠点:
  • 简单工厂和工厂方法都有一个优点,服务器端的具体产品类名变化后,客户端不知道。但是工厂方法中,客户端代码依然依赖于服务端的具体工厂类名,服务端一改,客户端也要跟着修改。
解释: 
工厂的名字,是被视为接口的,服务端作者有责任和义务保证工厂名字的稳定。
虽然客户端依赖于工厂的具体类名,可是在IT业内所有工厂的名字都是趋于稳定的,
至少工厂类名的名字比具体产品类名的名字更加稳定。
  • 既然产品是客户端自己扩展出来的,为什么不直接自己实例化呢?怎么修改自己都能把控,为什么还要创建产品工厂的类呢?
因为服务端原作者开发功能时,除了开发一些抽象产品、具体产品、对应的工厂,还会配套搭建一些提前做好的框架和业务。
为了适应原有的架构,需要创建具体产品和具体工厂,而不是直接使用具体产品。
案例

工厂创建电脑->富士康工厂
华为工厂、三星工厂、苹果工厂、联想工厂…
如何知道你制造出来的产品是电脑?
因为:电脑标准规范(协议、接口)->特点
角色一:抽象产品->定义产品规范(规格)->电脑规范
角色二:具体产品->具体实现(具体制造目标)->具体电脑 具体电脑:华为电脑、三星电脑、苹果电脑…
角色三:抽象工厂->定义工厂规范和标准
角色四:具体工厂->华为工厂、三星工厂

角色一:抽象产品->ComputerProtocol
角色二:具体产品->SXComputer、HWComputer、MacComputer…
角色三:抽象工厂->ComputerFactoryProtocol
角色四:具体工厂->SXComputerFactory、HWComputerFactory…

示例程序
角色一:抽象工厂 
//电脑工厂标准
//程序中->引用关系
//判断的依据
@protocol ComputerFactoryProtocol

//流水线
-(id)getComputer;

@end
//角色三:抽象产品  电脑规范
@protocol ComputerProtocol

//处理器
-(void)cpu;

//显卡
-(void)displaycard;

//主板
-(void)mainborad;

@end
//角色二:  具体工厂 
@interface SXComputerFactory : NSObject

@end

@implementation SXComputerFactory

-(id)getComputer{
    return [[SXComputer alloc] init];
}

@end

@interface HWComputerFactory : NSObject

@end


@implementation HWComputerFactory

-(id)getComputer{
    return [[HWComputer alloc] init];
}

@end

//角色四: 具体产品
@interface SXComputer : NSObject

@end

@implementation SXComputer

//处理器
-(void)cpu{
    NSLog(@"三星处理器");
}

//显卡
-(void)displaycard{
    NSLog(@"三星显卡");
}

//主板
-(void)mainborad{
    NSLog(@"三星主板");
}

@end


@interface HWComputer : NSObject

@end

@implementation HWComputer

//处理器
-(void)cpu{
    NSLog(@"华为处理器");
}

//显卡
-(void)displaycard{
    NSLog(@"华为显卡");
}

//主板
-(void)mainborad{
    NSLog(@"华为主板");
}

@end
抽象工厂模式
  • 定义
    抽象工厂模式与工厂方法模式解决的问题类似。不同的是,抽象工厂模式的作用是创建一组相互关联,却又不存在共同协议或者基类的对象。
工厂方法模式->角色划分

角色一:抽象产品
角色二:具体产品
角色三:抽象工厂
角色四:具体工厂

UML图
抽象工厂模式UML.png
产品等级/产品簇
产品等级:产品簇 .png
优点
  • 依然有简单工厂和工厂方法的优点。
  • 抽象工厂把工厂方法中工厂类的数量减少了,无论多少个产品等级,无论多少个产品等级,同一类产品簇就只需要一个工厂类。
缺点

当产品等级发生变化时(增加或者删除产品等级),都要引起所有以前工厂代码的修改。这就违反了”开闭原则“。

杠点

为什么三秦工厂中,必须是米线搭配冰峰呢,为什么不能米线搭配口乐?

根据抽象工厂的定义,抽象工厂中可以生成多个产品,这多个产品之间,就必须有内在的联系。
同一个工厂中的产品都属于同一个产品簇,不能把不同产品簇中的产品混合到一个抽象工厂的实现类中。 
结论

当产品等级比较固定时,可以考虑使用抽象工厂。如果产品等级经常变化,则不建议使用抽象工厂。
如果产品等级只有一个,或者较少,那工厂方法比抽象工厂更加适用。
如果产品不需要扩充,那简单工厂最好。
如果产品经常扩展,那就使用工厂方法。
如果产品等级很多,那就使用抽象工厂。
如果产品等级经常变化,那就不适用使用工厂了。

你可能感兴趣的:(简单工厂/工厂方法/抽象工厂)