在简单工厂方法模式,工厂方法模式与java抽象的原则是什么工厂模式中,哪个模式符合开闭原则

工厂模式|LOFTER(乐乎) - 记录生活,发现同好
LOFTER for ipad —— 记录生活,发现同好
&nbsp&nbsp被喜欢
&nbsp&nbsp被喜欢
{list posts as post}
{if post.type==1 || post.type == 5}
{if !!post.title}${post.title|escape}{/if}
{if !!post.digest}${post.digest}{/if}
{if post.type==2}
{if post.type == 3}
{if !!post.image}
{if post.type == 4}
{if !!post.image}
{if !!photo.labels && photo.labels.length>0}
{var wrapwidth = photo.ow < 500?photo.ow:500}
{list photo.labels as labs}
{var lbtxtwidth = Math.floor(wrapwidth*(labs.ort==1?labs.x:(100-labs.x))/100)-62}
{if lbtxtwidth>12}
{if !!labs.icon}
{list photos as photo}
{if photo_index==0}{break}{/if}
品牌${make||'-'}
型号${model||'-'}
焦距${focalLength||'-'}
光圈${apertureValue||'-'}
快门速度${exposureTime||'-'}
ISO${isoSpeedRatings||'-'}
曝光补偿${exposureBiasValue||'-'}
镜头${lens||'-'}
{if data.msgRank == 1}{/if}
{if data.askSetting == 1}{/if}
{if defined('posts')&&posts.length>0}
{list posts as post}
{if post_index < 3}
{if post.type == 1 || post.type == 5}
{if !!post.title}${post.title|escape}{/if}
{if !!post.digest}${post.digest}{/if}
{if post.type == 2}
{if post.type == 3}
{if post.type == 4}
{if post.type == 6}
{if drlist.length>0}
更多相似达人:
{list drlist as dr}{if drlist.length === 3 && dr_index === 0}、{/if}{if drlist.length === 3 && dr_index === 1}、{/if}{if drlist.length === 2 && dr_index === 0}、{/if}{/list}
暂无相似达人,
{if defined('posts')&&posts.length>0}
{list posts as post}
{if post.type == 2}
{if post.type == 3}
{if post.type == 4}
{if post.type == 6}
this.p={ currentPage:1,pageNewMode:true,isgooglead3:false,ishotrecompost:false,visitorId:0, first:'',tag:'工厂模式',recommType:'new',recommenderRole:0,offset:20,type:0,isUserEditor:0,};距离上次更新博客已经过去10天了,按计划这篇博客早该更新了,可计划赶不上变化由于事情太多,导致该计划不断延期,这不终于有块空闲时间了,得赶紧补上。哈哈。
好了,言归正传,今天我给大家说说php中的工厂模式。
工厂模式可分为简单工厂、工厂和抽象工厂,具体区别是什么呢?下面我们通过实例来一步一步讲解:
首先我们设想一个任务场景:
假设有个关于个人事务管理的项目,功能之一就是管理Appointment(预约)对象。我们的业务团队和A公司建立了关系,目前需要使用一个叫做BloggsCal格式来和他们交流预约相关的数据。但是业务部门提醒可能会有更多的数据格式。
任务分析:
因为解码器可能会有多种,为了避免在逻辑代码中使用过多的if else,这里需要使用工厂模式来将创造者和使用者分开,此时需要两个类,一个类AppEncoder用于定义一个解码器,将A公司传来的数据解码;另外一个类CommsManager用于获取该解码器,用于与A公司进行通信。使用模式术语说,CommsManager就是创造者,AppEncoder就是产品。(一个创造者、一个产品,将类的实例化和对象的使用分离开,这就是工厂模式的思想)
上面的任务场景我们可以通过简单工厂模式实现,具体代码如下:
2 //产品类
3 class BloggsApptEncoder {
function encode()
return "Appointment data encoded in BloggsCal format\n";
<span style="color: # //创造者类
<span style="color: # class CommsManager {
<span style="color: #
function static getBloggsApptEncoder()
<span style="color: #
<span style="color: #
return new BloggsApptEncoder();<span style="color: #
} <span style="color: # }
使用方法比较简单,这里不做赘述。
此时又有新的需求,业务部门告诉我们需要新增一种数据格式MegCal,来完成数据交流。此时我们需要新增对应的解码器类,然后直接在commsManager新增参数来标识需要实例化哪个解码器。代码如下:
class CommsManager {
const BLOGGS = 1;
const MEGA = 2;
private $mode;
public function __construct( $mode )
$this-&mode = $mode;
function getApptEncoder()
switch($this-&mode) {
case (self::MEGA):
return new MegaApptEncoder();
return new BloggsApptEncoder();
这便是简单工厂模式了。那么它带来了什么好处呢?首先,符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责“消费”产品(正如暴发户所为)。下面我们从开闭原则上来分析下简单工厂模式。当新增一种数据格式的时候,只要符合抽象产品格式,那么只要通知工厂类知道就可以被使用了。(即创建一个新的解码器类,继承抽象解码器ApptEncoder)那么对于产品部分来说,它是符合开闭原则的——对扩展开放、对修改关闭;但是工厂类不太理想,因为每增加一各格式,都要在工厂类中增加相应的商业逻辑和判断逻辑,这显自然是违背开闭原则的。
而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了。因此简单工厂模式只适用于业务简单的情况下或者具体产品很少增加的情况。而对于复杂的业务环境可能不太适应了。这就应该由工厂方法模式来出场了!!
业务部门的新需求来了:
每种格式的预约数据中,需要提供页眉和页脚来描述每次预约
扩展之前我们用简单工厂模式来实现上述功能,具体代码如下:
// 简单工厂模式class CommsManager {
const BLOGGS = 1;
const MEGA = 2;
private = $mode;
public function __construct( $mode )
$this-&mode = $mode;
// 生成解码器对应的页眉
public function getHeaderText()
switch( $this-&mode ) {
case ( self::MEGA ):
return "MegaCal header\n";
return "BloggsCal header\n";
// 生成解码器
public function getApptEncoder()
switch( $this-&mode ) {
case ( self::MEGA ):
return new MegaApptEncoder();
return new BloggsApptEncoder();;
可见:此时相同的条件语句switch在不同的方法中出现了重复,而且如果添加新的数据格式需要改动的类过多。所以需要对我们的结构进行修改,以求更容易扩展和维护,我们可以使用创造者子类分别生成对应的产品,这样添加新的数据格式时,只需要添加一个创造者子类即可,方便扩展和维护。具体代码如下:
// 工厂模式abstract class CommsManager {
abstract function getHeaderText();
abstract function getApptEncoder();
abstract function getFooterText();
class BloggsCommsManager extends CommsManager {
function getHeaderText()
return "BloggsCal Header\n";
function getApptEncoder()
return new BloggsApptEncoder();
function getFooterText()
return "BloggsCal Footer\n";
class MegaCommsManager extends CommsManager {
function getHeaderText()
return "MegaCal Header\n";
function getApptEncoder()
return new MegaApptEncoder();
function getFooterText()
return "MegaCal Footer\n";
此时,如果有新的数据格式,只需要添加一个创造类的子类即可。此时想获取MegaCal对应的解码器直接通过MegaCommsManager::getApptEncoder()获取即可;当前架构已经可以满足目前的需求,但是别得意哦,这些讨厌的产品又来需求了,他们不仅需要和A公司交流预约数据(Appointment),还需要交流待办事宜(Ttd)、联系人(Contact)等数据。同样的这些数据交流的格式也是BloggsCal和MegaCal.那么我们该如何设计呢?直接在对应解码器的子类中添加处理事宜(TtD)和联系人(Contact)的方法,代码如下:
// 抽象工厂模式abstract class CommsManager {
abstract function getHeaderText();
abstract function getApptEncoder();
abstract function getTtdEncoder();
abstract function getContactEncoder();
abstract function getFooterText();
class BloggsCommsManager extends CommsManager {
function getHeaderText()
return "BloggsCal Header\n";
function getApptEncoder()
return new BloggsApptEncoder();
function getTtdEncoder()
return new BloggsTtdEncoder();
function getContactEncoder()
return new BloggsContactEncoder();
function getFooterText()
return "BloggsCal Footer\n";
class MegaCommsManager extends CommsManager {
function getHeaderText()
return "MegaCal Header\n";
function getApptEncoder()
return new MegaApptEncoder();
function getTtdEncoder()
return new MegaTtdEncoder();
function getContactEncoder()
return new
MegaContactEncoder();
function getFooterText()
return "MegaCal Footer\n";
//当然需要添加对应的TtdEncoder抽象类和ContactEncoder抽象类,以及他们的子类。
上面就是工厂模式和及其变形,核心在于:
1.将系统和实现的细节分离开。我们可在示例中移除或者添加任意数目的编码格式而不会影响系统。
2.对系统中功能相关的元素强制进行组合。因此,通过使用BloggsCommsManager,可以确定只使用与BloggsCal有关的类。
3.添加新产品时将会令人苦恼。因为不仅需要创建新产品的具体实现,而且为了支持它,我们必须修改抽象创建者和它的每个具体实现。
我们可以做出优化,可以创建一个标志参数来决定返回什么对象的单一的make()方法,而不用给每个工厂创建独立的方法。代码如下:
abstract class CommsManager {
const APPT = 1;
const TTD = 2;
const CONTACT = 3;
abstract function getHeaderText();
abstract function make ( $flag_init
abstract function getFooterText();
class BloggsCommsManager extends CommsManager {
function getHeaderText()
return "BloggsCal Header\n";
function make( $flag_init )
switch ($flag_init) {
case self::APPT:
return new BloggsApptEncoder();
case self::TTD:
return new BloggsTtdEncoder();
case self::CONTACT:
return new BloggsContactEncoder();
function getFooterText()
return "BloggsCal Header\n";
如果还需要添加交流其它的数据,此时只需在抽象创造者中添加一个新的flag_init标识,并在子创造者中的make方法中添加一个条件。相比来说比原先的更加容易扩展。只需修改少数地方即可。
简单工厂:适用于生成数量少,功能简单的产品(BloggApptEncoder和MegaApptEncoder)
工厂模式:适用于生成数量多,功能复杂的产品(多个产品树[BloggCal,MegaCal]、单个产品族[apptEncoder]),相比简单工厂来说:业务更复杂,功能更多,但是产品族还是单个。
抽象工厂:适用于生成多个产品族、多个产品树的情景(产品族[appt,ttd,contact],产品树[Bloggcal,megaCal])。相比于工厂模式,更容易扩展添加新的产品族。
以上就是我对php中简单工厂、工厂模式和抽象工厂的初步理解,感谢您的阅读
注:因本人的技术有限,如果有理解错误的地方,还请各位批评指正,共同交流学习,谢谢。我会继续努力的。
阅读(...) 评论()设计模式——简单工厂,工厂方法,抽象工厂 - 简书
设计模式——简单工厂,工厂方法,抽象工厂
本文csdn地址:设计模式在工作中经常会用到:
创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式(7):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式(11):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
本身设计模式的诞生,也是基于设计模式的六大原则:
单一职责原则(Single Responsibility Principle)
里氏替换原则(Liskov Substitution Principle)
依赖倒置原则(Dependence Inversion Principle)
接口隔离原则(Interface Segregation Principle)
迪米特法则(Law Of Demeter)
开闭原则(Open Close Principle)
具体这六大原则的含义,可以参考。
我自己在用设计模式的过程当中,主要感觉到其实设计模式有以下作用:
更方便模块的复用和测试
方便看懂和修改另一个写的代码!
本文主要以代码形式实现每一种设计模式,算是自己的一种复习和实践。相应的代码,也会放到上。本文的类图均来自于《Objective-C编程之道 iOS设计模式解析》。
本篇主要讲:
0.简单工厂
简单工厂本身并不是23种设计模式的一种,更比较像一种编程习惯,但也是经常使用。《Head First》的例子:客户到pizza store点不同类型的pizza,有cheese的,也有clam的。
#import &Foundation/Foundation.h&
typedef NS_ENUM(NSInteger, PizzaType){
@interface SFPizza : NSObject
#import "SFPizza.h"
@interface SFCheesePizza : SFPizza
@interface SFClamPizza : SFPizza
Simple Factory:
#import &Foundation/Foundation.h&
#import "SFPizza.h"
@interface SFPizzaSimpleFactory : NSObject
- (SFPizza *) createPizza:(PizzaType) pizzaT
#import "SFPizzaSimpleFactory.h"
#import "SFCheesePizza.h"
#import "SFClamPizza.h"
@implementation SFPizzaSimpleFactory
- (SFPizza *) createPizza:(PizzaType) pizzaType{
SFPizza *pizza =
if (pizzaType == Cheese){
pizza = [[SFCheesePizza alloc]init];
}else if (pizzaType == Clam){
pizza = [[SFClamPizza alloc]init];
Pizza Store:
#import &Foundation/Foundation.h&
#import "SFPizza.h"
@interface SFPizzaStore : NSObject
- (SFPizza *) orderPizza:(PizzaType)pizzaT
#import "SFPizzaStore.h"
#import "SFPizzaSimpleFactory.h"
@interface SFPizzaStore(){
SFPizzaSimpleFactory *_simpleF
@implementation SFPizzaStore
- (instancetype)init{
self = [super init];
if ( self ){
_simpleFactory = [[SFPizzaSimpleFactory alloc]init];
- (SFPizza *) orderPizza:(PizzaType)pizzaType{
SFPizza *pizza = [_simpleFactory createPizza:pizzaType];
[pizza prepare];
[pizza bake];
[pizza cut];
[pizza box];
1.工厂方法
概念:定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到子类。
Paste_Image.png
何时使用:
编译时无法准备预期要创建的对象的类
类想让其子类决定在运行时创建什么
类有若干辅助类为子类,而你想将返回哪个子类这一信息局部化
《Head First》的例子:纽约和芝加哥的pizza store有各自差异化的风味,提供当地风格的cheese和clam的pizza。
#import &Foundation/Foundation.h&
typedef NS_ENUM(NSInteger, PizzaType){
@interface FMPizza : NSObject
#import "FMPizza.h"
@interface FMNYCheesePizza : FMPizza
@interface FMNYClamPizza : FMPizza
@interface FMChicagoCheesePizza : FMPizza
@interface FMChicagoClamPizza : FMPizza
pizza store抽象:
#import &Foundation/Foundation.h&
#import "FMPizza.h"
@protocol FMPizzaStore &NSObject&
- (FMPizza *) createPizza:(PizzaType)pizzaT
- (FMPizza *) orderPizza:(PizzaType)pizzaT
pizza store实现:
#import &Foundation/Foundation.h&
#import "FMPizzaStore.h"
@interface FMNYPizzaStore : NSObject&FMPizzaStore&
#import "FMNYPizzaStore.h"
#import "FMNYCheesePizza.h"
#import "FMNYClamPizza.h"
@implementation FMNYPizzaStore
- (FMPizza *) createPizza:(PizzaType)pizzaType{
FMPizza *pizza =
if (pizzaType == Cheese){
pizza = [[FMNYCheesePizza alloc]init];
} else if (pizzaType == Clam){
pizza = [[FMNYClamPizza alloc]init];
- (FMPizza *) orderPizza:(PizzaType)pizzaType{
FMPizza *pizza = [self createPizza:pizzaType];
[pizza prepare];
[pizza bake];
[pizza cut];
[pizza box];
#import &Foundation/Foundation.h&
#import "FMPizzaStore.h"
@interface FMChicagoPizzaStore : NSObject&FMPizzaStore&
#import "FMChicagoPizzaStore.h"
#import "FMChicagoCheesePizza.h"
#import "FMChicagoClamPizza.h"
@implementation FMChicagoPizzaStore
- (FMPizza *) createPizza:(PizzaType)pizzaType{
FMPizza *pizza =
if (pizzaType == Cheese){
pizza = [[FMChicagoCheesePizza alloc]init];
} else if (pizzaType == Clam){
pizza = [[FMChicagoClamPizza alloc]init];
- (FMPizza *) orderPizza:(PizzaType)pizzaType{
FMPizza *pizza = [self createPizza:pizzaType];
[pizza prepare];
[pizza bake];
[pizza cut];
[pizza box];
2.抽象工厂
概念:提供一个创建一系列相关或相互以来对象的接口,而无需指定它们的具体的类。
Paste_Image.png
何时使用:
系统需要屏蔽有关对象如何创建,如何组织和如何表达
系统需要由关联的多个对象来构成
有关联的多个对象需要一起应用并且它们的约束是强迫的(不可分离)。
你想提供一组对象而不显示它们的实现过程,只显示它们的接口。
抽象工厂和工厂方法的区别:抽象工厂:
通过对象组合创建抽象产品
创建多系列产品
必须修改父类的接口才能支持新的产品
工厂方法:
通过类继承创建抽象产品
创建一种产品
子类化创建者并重载工厂方法以创建新的产品
《Head First》的例子:纽约和芝加哥的pizza store提供的cheese和clam的pizza,但原料不同,做出来的pizza也不同。
@interface AFCheese : NSObject
@interface AFNYCheese : AFCheese
@interface AFChicagoCheese : AFCheese
@interface AFClam : NSObject
@interface AFNYClam : AFClam
@interface AFChicagoClam : AFClam
@interface AFSauce : NSObject
#import &Foundation/Foundation.h&
#import "AFCheese.h"
#import "AFClam.h"
#import "AFSauce.h"
#import "AFPizzaIngredientFactory.h"
typedef NS_ENUM(NSInteger, PizzaType){
@interface AFPizza : NSObject
@property (nonatomic, strong) AFCheese
@property (nonatomic, strong) AFClam
@property (nonatomic, strong) AFSauce
- (instancetype)initWithPizzaIngredientFactory:(id&AFPizzaIngredientFactory&)
#import "AFPizza.h"
@implementation AFPizza
- (instancetype)initWithPizzaIngredientFactory:(id&AFPizzaIngredientFactory&) factory{
self = [super init];
- (void) prepare{
- (void) bake{
NSLog(@"start bake");
- (void) cut{
NSLog(@"start cut");
- (void) box{
NSLog(@"start box");
pizza 子类:
#import "AFPizza.h"
@interface AFCheesePizza : AFPizza
#import "AFCheesePizza.h"
@interface AFCheesePizza(){
id&AFPizzaIngredientFactory& _
@implementation AFCheesePizza
- (instancetype)initWithPizzaIngredientFactory:(id&AFPizzaIngredientFactory&) factory{
self = [super init];
if (self){
_factory =
- (void)prepare{
self.cheese = [_factory createCheese];
self.sauce
= [_factory createSource];
#import "AFPizza.h"
@interface AFClamPizza : AFPizza
#import "AFClamPizza.h"
@interface AFClamPizza(){
id&AFPizzaIngredientFactory& _
@implementation AFClamPizza
- (instancetype)initWithPizzaIngredientFactory:(id&AFPizzaIngredientFactory&) factory{
self = [super init];
if (self){
_factory =
- (void)prepare{
= [_factory createClam];
self.sauce
= [_factory createSource];
pizza ingredient factory 抽象
#import &Foundation/Foundation.h&
@class AFC
@class AFC
@class AFS
@protocol AFPizzaIngredientFactory
- (AFCheese *)
- (AFClam *)
- (AFSauce *)
pizza ingredient factory 实现
#import &Foundation/Foundation.h&
#import "AFPizzaIngredientFactory.h"
@interface AFNYPizzaIngredientFactory : NSObject&AFPizzaIngredientFactory&
#import "AFNYPizzaIngredientFactory.h"
#import "AFNYCheese.h"
#import "AFNYClam.h"
#import "AFSauce.h"
@implementation AFNYPizzaIngredientFactory
- (AFCheese *) createCheese{
return [[AFNYCheese alloc]init];
- (AFClam *) createClam{
return [[AFNYClam alloc]init];
- (AFSauce *) createSource{
return [[AFSauce alloc]init];
#import &Foundation/Foundation.h&
#import "AFPizzaIngredientFactory.h"
@interface AFChicagoIngredientFactory : NSObject&AFPizzaIngredientFactory&
#import "AFChicagoIngredientFactory.h"
#import "AFChicagoCheese.h"
#import "AFChicagoClam.h"
#import "AFSauce.h"
@implementation AFChicagoIngredientFactory
- (AFCheese *) createCheese{
return [[AFChicagoCheese alloc]init];
- (AFClam *) createClam{
return [[AFChicagoClam alloc]init];
- (AFSauce *) createSource{
return [[AFSauce alloc]init];
pizza store抽象:
#import &Foundation/Foundation.h&
#import "AFPizza.h"
@protocol AFPizzaStore
- (AFPizza *) createPizza:(PizzaType)pizzaT
- (AFPizza *) orderPizza:(PizzaType)pizzaT
pizza store实现:
#import &Foundation/Foundation.h&
#import "AFPizzaStore.h"
@interface AFNYPizzaStore : NSObject&AFPizzaStore&
#import "AFNYPizzaStore.h"
#import "AFNYPizzaIngredientFactory.h"
#import "AFCheesePizza.h"
#import "AFClamPizza.h"
@implementation AFNYPizzaStore
- (AFPizza *) createPizza:(PizzaType)pizzaType{
AFPizza *pizza =
AFNYPizzaIngredientFactory *factory = [[AFNYPizzaIngredientFactory alloc]init];
if ( pizzaType == Cheese ){
pizza = [[AFCheesePizza alloc]initWithPizzaIngredientFactory:factory];
}else if ( pizzaType == Clam ){
pizza = [[AFClamPizza alloc]initWithPizzaIngredientFactory:factory];
- (AFPizza *) orderPizza:(PizzaType)pizzaType{
AFPizza *pizza = [self createPizza:pizzaType];
[pizza prepare];
[pizza bake];
[pizza cut];
[pizza box];
#import &Foundation/Foundation.h&
#import "AFPizzaStore.h"
@interface AFChicagoPizzaStore : NSObject&AFPizzaStore&
#import "AFChicagoPizzaStore.h"
#import "AFChicagoIngredientFactory.h"
#import "AFCheesePizza.h"
#import "AFClamPizza.h"
@implementation AFChicagoPizzaStore
- (AFPizza *) createPizza:(PizzaType)pizzaType{
AFPizza *pizza =
AFChicagoIngredientFactory *factory = [[AFChicagoIngredientFactory alloc]init];
if ( pizzaType == Cheese ){
pizza = [[AFCheesePizza alloc]initWithPizzaIngredientFactory:factory];
}else if ( pizzaType == Clam ){
pizza = [[AFClamPizza alloc]initWithPizzaIngredientFactory:factory];
- (AFPizza *) orderPizza:(PizzaType)pizzaType{
AFPizza *pizza = [self createPizza:pizzaType];
[pizza prepare];
[pizza bake];
[pizza cut];
[pizza box];
一些个人总结
1.什么时候会去用工厂模式?(简单工厂,工厂方法,抽象工厂)为了不再需要直接创建对象,降低代码耦合度。对于创建多种具有同一系列行为的物体,使用工厂方法。对于产品族使用抽象工厂。2.简单工厂的缺点简单工厂主要违反了开闭原则:对扩展开放,对修改关闭。添加一种对象,就要去修改简单工厂中的获取对象方法。
1.《Objective-C编程之道 iOS设计模式解析》2.《Head First设计模式》3.4.
github:/game3108一.前言  
话说十年前,有一个爆发户,他家有三辆汽车(Benz(奔驰)、Bmw(宝马)、Audi(奥迪)),还雇了司机为他开车。不过,爆发户坐车时总是这样:上Benz车后跟司机说&开奔驰车!&,坐上Bmw后他说&开宝马车!&,坐上 Audi后他说&开奥迪车!&。你一定说:这人有病!直接说开车不就行了?!而当把这个爆发户的行为放到我们程序语言中来,我们发现C语言一直是通过这种方式来坐车的
幸运的是这种有病的现象在OO语言中可以避免了。下面以Java语言为基础来引入我们本文的主题:工厂模式!
工厂模式主要是为创建对象提供了接口。工厂模式按照《Java与模式》中的提法分为三类:1. 简单工厂模式(Simple Factory)2. 工厂方法模式(Factory Method)3. 抽象工厂模式(Abstract Factory)这三种模式从上到下逐步抽象,并且更具一般性。还有一种分类法,就是将简单工厂模式看为工厂方法模式的一种特例,两个归为一类。两者皆可,这本为使用《Java与模式》的分类方法。在什么样的情况下我们应该记得使用工厂模式呢?大体有两点:1.在编码时不能预见需要创建哪种类的实例。2.系统不应依赖于产品类实例如何被创建、组合和表达的细节工厂模式能给我们的OOD、OOP带来哪些好处呢??
三.简单工厂模式
这个模式本身很简单而且使用在业务较简单的情况下。一般用于小项目或者具体产品很少扩展的情况(这样工厂类才不用经常更改)。它由三种角色组成:工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,根据逻辑不同,产生具体的工厂产品。如例子中的Driver类。抽象产品角色:它一般是具体产品继承的父类或者实现的接口。由接口或者抽象类来实现。如例中的Car接口。具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现,如例子中的Benz、Bmw类。
来用类图来清晰的表示下的它们之间的关系:
下面就来给那个暴发户治病:在使用了简单工厂模式后,现在暴发户只需要坐在车里对司机说句:&开车&就可以了。来看看怎么用代码实现的:(为方便起见,所有的类放在一个文件中,故有一个类被声明为public)
1 //抽象产品
2 abstract class Car{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
14 //具体产品
15 class Benz extends Car{
public void drive(){
System.out.println(this.getName()+"----go-----------------------");
21 class Bmw extends Car{
public void drive(){
System.out.println(this.getName()+"----go-----------------------");
27 //简单工厂
28 class Driver{
public static Car createCar(String car){
Car c = null;
if("Benz".equalsIgnoreCase(car))
c = new Benz();
else if("Bmw".equalsIgnoreCase(car))
c = new Bmw();
40 public class BossSimplyFactory {
public static void main(String[] args) throws IOException {
//老板告诉司机我今天坐奔驰
Car car = Driver.createCar("benz");
car.setName("benz");
//司机开着奔驰出发
car.drive();
如果老板要坐奥迪,同理。
这便是简单工厂模式了。那么它带了了什么好处呢?首先,符合现实中的情况;而且客户端免除了直接创建产品对象的责任,而仅仅负责&消费&产品(正如暴发户所为)。下面我们从开闭原则上来分析下简单工厂模式。当暴发户增加了一辆车的时候,只要符合抽象产品制定的合同,那么只要通知工厂类知道就可以被客户使用了。(即创建一个新的车类,继承抽象产品Car)那么 对于产品部分来说,它是符合开闭原则的&&对扩展开放、对修改关闭;但是工厂类不太理想,因为每增加一辆车,都要在工厂类中增加相应的商业逻辑和判 断逻辑,这显自然是违背开闭原则的。
而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这些产品,所以这可能会把我们的上帝类坏了。
正如我前面提到的简单工厂模式适用于业务简单的情况下或者具体产品很少增加的情况。而对于复杂的业务环境可能不太适应了。这就应该由工厂方法模式来出场了!!
四.工厂方法模式
抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。来用类图来清晰的表示下的它们之间的关系:
话说暴发户生意越做越大,自己的爱车也越来越多。这可苦了那位司机师傅了,什么车它都要记得,维护,都要经过他来使用!于是暴发户同情他说:我给你分配几个人手,你只管管好他们就行了!于是工厂方法模式的管理出现了。代码如下:
1 //抽象产品
2 abstract class Car{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
14 //具体产品
15 class Benz extends Car{
public void drive(){
System.out.println(this.getName()+"----go-----------------------");
20 class Bmw extends Car{
public void drive(){
System.out.println(this.getName()+"----go-----------------------");
27 //抽象工厂
28 abstract class Driver{
public abstract Car createCar(String car) throws E
31 //具体工厂(每个具体工厂负责一个具体产品)
32 class BenzDriver extends Driver{
public Car createCar(String car) throws Exception {
return new Benz();
37 class BmwDriver extends Driver{
public Car createCar(String car) throws Exception {
return new Bmw();
44 public class Boss{
public static void main(String[] args) throws Exception {
Driver d = new BenzDriver();
Car c = d.createCar("benz");
c.setName("benz");
c.drive();
使用开闭原则来分析下工厂方法模式。当有新的产品(即暴发户的汽车)产生时,只要按照抽象产品角色、抽象工厂角色提供的合同来生成,那么就可以被客户使用,而不必去修改任何已有的代码。(即当有新产品时,只要创建并基础抽象产品;新建具体工厂继承抽象工厂;而不用修改任何一个类)工厂方法模式是完全符合开闭原则的!
使用工厂方法模式足以应付我们可能遇到的大部分业务需求。但是当产品种类非常多时,就会出现大量的与之对应的工厂类,这不应该是我们所希望的。所以我建议在这种情况下使用简单工厂模式与工厂方法模式相结合的方式来减少工厂类:即对于产品树上类似的种类(一般是树的叶子中互为兄弟的)使用简单工厂模式来实现。当然特殊的情况,就要特殊对待了:对于系统中存在不同的产品树,而且产品树上存在产品族(下一节将解释这个名词)。那么这种情况下就可能可以使用抽象工厂模式了。
让我们来看看简单工厂模式、工厂方法模式给我们的启迪:如果不使用工厂模式来实现我们的例子,也许代码会减少很多&&只需要实现已有的车,不使用多态。但是在可维护性上,可扩展性上是非常差的(你可以想象一下添加一辆车后要牵动的类)。因此为了提高扩展性和维护性,多写些代码是值得的。
六、抽象工厂模式
先来认识下什么是产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。
图中的BmwCar和BenzCar就是两个产品树(产品层次结构);而如图所示的BenzSportsCar和BmwSportsCar就是一个产品族。他们都可以放到跑车家族中,因此功能有所关联。同理BmwBussinessCar和BenzBusinessCar也是一个产品族。可以这么说,它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象。而且使用抽象工厂模式还要满足一下条件:1.系统中有多个产品族,而系统一次只可能消费其中一族产品2.同属于同一个产品族的产品以其使用。来看看抽象工厂模式的各个角色(和工厂方法的如出一辙):抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。
1 //抽象产品(Bmw和Audi同理)
2 abstract class BenzCar{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
14 //具体产品(Bmw和Audi同理)
15 class BenzSportCar extends BenzCar{
public void drive(){
System.out.println(this.getName()+"----BenzSportCar-----------------------");
20 class BenzBusinessCar extends BenzCar{
public void drive(){
System.out.println(this.getName()+"----BenzBusinessCar-----------------------");
26 abstract class BmwCar{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
38 class BmwSportCar extends BmwCar{
public void drive(){
System.out.println(this.getName()+"----BmwSportCar-----------------------");
43 class BmwBusinessCar extends BmwCar{
public void drive(){
System.out.println(this.getName()+"----BmwBusinessCar-----------------------");
49 abstract class AudiCar{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
61 class AudiSportCar extends AudiCar{
public void drive(){
System.out.println(this.getName()+"----AudiSportCar-----------------------");
66 class AudiBusinessCar extends AudiCar{
public void drive(){
System.out.println(this.getName()+"----AudiBusinessCar-----------------------");
73 //抽象工厂
74 abstract class Driver3{
public abstract BenzCar createBenzCar(String car) throws E
public abstract BmwCar createBmwCar(String car) throws E
public abstract AudiCar createAudiCar(String car) throws E
81 //具体工厂
82 class SportDriver extends Driver3{
public BenzCar createBenzCar(String car) throws Exception {
return new BenzSportCar();
public BmwCar createBmwCar(String car) throws Exception {
return new BmwSportCar();
public AudiCar createAudiCar(String car) throws Exception {
return new AudiSportCar();
93 class BusinessDriver extends Driver3{
public BenzCar createBenzCar(String car) throws Exception {
return new BenzBusinessCar();
public BmwCar createBmwCar(String car) throws Exception {
return new BmwBusinessCar();
public AudiCar createAudiCar(String car) throws Exception {
return new AudiBusinessCar();
105 //老板
106 public class BossAbstractFactory {
public static void main(String[] args) throws Exception {
Driver3 d = new BusinessDriver();
AudiCar car = d.createAudiCar("");
car.drive();
其中:BenzSportCar和BenzBusinessCar属于产品树;同理BmwSportCar和BmwBusinessCar。而BenzSportCar和BmwSportCar和AudiSportCar属于产品族。
所以抽象工厂模式一般用于具有产品树和产品族的场景下。
抽象工厂模式的缺点:如果需要增加新的产品树,那么就要新增三个产品类,比如VolvoCar,VolvoSportCar,VolvoSportCar,并且要修改三个工厂类。这样大批量的改动是很丑陋的做法。
所以可以用简单工厂配合反射来改进抽象工厂:UML图略。
1 abstract class BenzCar{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
13 class BenzSportCar extends BenzCar{
public void drive(){
System.out.println(this.getName()+"----BenzSportCar-----------------------");
18 class BenzBusinessCar extends BenzCar{
public void drive(){
System.out.println(this.getName()+"----BenzBusinessCar-----------------------");
24 abstract class BmwCar{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
36 class BmwSportCar extends BmwCar{
public void drive(){
System.out.println(this.getName()+"----BmwSportCar-----------------------");
41 class BmwBusinessCar extends BmwCar{
public void drive(){
System.out.println(this.getName()+"----BmwBusinessCar-----------------------");
47 abstract class AudiCar{
public abstract void drive();
public String getName() {
public void setName(String name) {
this.name =
59 class AudiSportCar extends AudiCar{
public void drive(){
System.out.println(this.getName()+"----AudiSportCar-----------------------");
64 class AudiBusinessCar extends AudiCar{
public void drive(){
System.out.println(this.getName()+"----AudiBusinessCar-----------------------");
* 简单工厂通过反射改进抽象工厂及其子工厂
* @author Administrator
76 class Driver3{
public static BenzCar createBenzCar(String car) throws Exception {
return (BenzCar) Class.forName(car).newInstance();
public static BmwCar createBmwCar(String car) throws Exception {
return (BmwCar) Class.forName(car).newInstance();
public static AudiCar createAudiCar(String car) throws Exception {
return (AudiCar) Class.forName(car).newInstance();
89 //客户端
90 public class SimpleAndAbstractFactory {
public static void main(String[] args) throws Exception {
AudiCar car = Driver3.createAudiCar("com.java.pattendesign.factory.AudiSportCar");
car.drive();
&从策略一词来看,策略模式是种倾向于行为的模式.有点类似找仗时的做战方案,一般司令员在做战前都会根据实际情况做出几套不同的方案,如果当时情况有变,就会根据相应的条件来判定用哪一套方案来替换原定方案。但无论如何替换,替换多少次,仗还是要打的。
& 举例:导出成EXCEL,WORD,PDF文件的功能,这三类导出虽然具体操作略有不同,但是大部分都相同。
策略模式与工厂模式从uml图上来说,基本一致。只是强调的封装不同。我们以工厂模式和策略模式的比较来讲解策略模式。
工厂模式我们可以做如下理解:假设有Audi的公司生产汽车,它掌握一项核心的技术就是生产汽车,另一方面,它生产的汽车是有不同型号的,并且在不同的生产线上进行组装。当客户通过销售部门进行预定后,Audi公司将在指定的生产线上为客户生产出它所需要的汽车。
策略(Strategy)模式在结构上与工厂模式类似,唯一的区别是工厂模式实例化一个产品的操作是在服务端来做的,换句话说客户端传达给服务端的只是某种标识,服务端根据该标识实例化一个对象。而策略模式的客户端传达给服务端的是一个实例,服务端只是将该实例拿过去在服务端的环境里执行该实例的方法。这就好比一个对汽车不甚了解的人去买车,他在那一比划,说要什么什么样的,销售部门根据他的这个&比划&来形成一份订单,这就是工厂模式下的工作方式。而策略模式下那个顾客就是个行家,他自己给出了订单的详细信息,销售部门只是转了一下手就交给生产部门去做了。通过两相对比,我们不难发现,采用工厂模式必须提供足够灵活的销售部门,如果用户有了新的需求,销售部门必须马上意识到这样才可以做出合适的订单。所以倘一款新车出来了,生产部门和销售部门都需要更新,对顾客来说也需要更新对新车的描述所以需要改动的地方有三处。而策略模式中的销售部门工作比较固定,它只负责接受订单并执行特定的几个操作。当一款新车出来时,只需要对服务端的生产部门和客户端的代码进行更新,而不需要更新销售部门的代码。&
技术支持: 简单工厂和策略的基础都是因为面向对象的封装与多态。他们实现的思想都是先设定一个抽象的模型并从该模型派生出符合不同客户需求的各种方法,并加以封装。
工厂模式和策略模式的区别在于实例化一个对象的位置不同,对工厂模式而言,实例化对象是放在服务端的,即放在了工厂类里面;
而策略模式实例化对象的操作在客户端,服务端的&销售部门&只负责传递该对象,并在服务端的环境里执行特定的操作。。。
工厂模式要求服务端的销售部门足够灵敏,而策略模式由于对策略进行了封装,所以他的销售部门比较傻,需要客户提供足够能区分使用哪种策略的参数,而这最好的就是该策略的实例了。
1 //抽象产品
2 abstract class AudiCar{
public abstract void makeCar();
public String getName() {
public void setName(String name) {
this.name =
14 //具体产品
15 class AudiA6 extends AudiCar{
public void makeCar(){
System.out.println(this.getName()+"----go-----------------------");
20 class AudiA4 extends AudiCar{
public void makeCar(){
System.out.println(this.getName()+"----go-----------------------");
26 //销售部门----服务端
27 class CarContext {
AudiCar audiCar = null;
public CarContext(AudiCar audiCar) {
this.audiCar = audiC
public void orderCar(){
this.audiCar.makeCar();
39 //客户----客户端(这个客户是内行,什么都懂,他说我要A6,销售部门立刻给他a6,所以销售部门不用很懂)
40 public class SimplyFactoryAndStrategy2 {
public static void main(String[] args) throws IOException {
//客户说我要什么什么样子的车子,销售人员才知道他要什么样子的车子
AudiCar car = new AudiA6();
car.setName("a6");
CarContext context = new CarContext(car);
context.orderCar();
54 //工厂模式---与上面的策略模式比较
55 //抽象产品
56 abstract class AudiCar{
public abstract void makeCar();
public String getName() {
public void setName(String name) {
this.name =
68 //具体产品
69 class AudiA6 extends AudiCar{
public void makeCar(){
System.out.println(this.getName()+"----go-----------------------");
74 class AudiA4 extends AudiCar{
public void makeCar(){
System.out.println(this.getName()+"----go-----------------------");
80 //简单工厂---销售部门----服务端
81 class CarFactroy{
public static AudiCar createCar(String car){
AudiCar c = null;
if("A6".equalsIgnoreCase(car))
c = new AudiA6();
else if("A4".equalsIgnoreCase(car))
c = new AudiA4();
92 //客户----客户端(这个客户是外行,什么都不懂,只要随便描述下车,销售部门才能知道他要那款车,所以销售部门比较牛)
93 public class SimplyFactoryAndStrategy {
public static void main(String[] args) throws IOException {
System.out.print("请输入您要坐的车:(A6、A4)");
String carName = new BufferedReader(new InputStreamReader(System.in)).readLine();
//客户说我要什么什么样子的车子,销售人员才知道他要什么样子的车子
AudiCar car = CarFactroy.createCar(carName);
car.setName(carName);
car.makeCar();
策略模式的优缺点
& 策略模式的主要优点有:
策略类之间可以自由切换,由于策略类实现自同一个抽象,所以他们之间可以自由切换。
易于扩展,增加一个新的策略对策略模式来说非常容易,基本上可以在不改变原有代码的基础上进行扩展。
避免使用多重条件,如果不使用策略模式,对于所有的算法,必须使用条件语句进行连接,通过条件判断来决定使用哪一种算法,在上一篇文章中我们已经提到,使用多重条件判断是非常不容易维护的。
& 策略模式的缺点主要有两个:
维护各个策略类会给开发带来额外开销,可能大家在这方面都有经验:一般来说,策略类的数量超过5个,就比较令人头疼了。
必须对 客户端(调用者)暴露所有的策略类,因为使用哪种策略是由客户端来决定的,因此,客户端应该知道有什么策略,并且了解各种策略之间的区别,否则,后果很严 重。例如,有一个排序算法的策略模式,提供了快速排序、冒泡排序、选择排序这三种算法,客户端在使用这些算法之前,是不是先要明白这三种算法的适用情况? 再比如,客户端要使用一个容器,有链表实现的,也有数组实现的,客户端是不是也要明白链表和数组有什么区别?就这一点来说是有悖于迪米特法则的。
&&&&&&& 做面向对象设计的,对策略模式一定很熟悉,因为它实质上就是面向对象中的继承和多态,在看完策略模式的通用代码后,我想,即使之前从来没有听说过策略模式,在开发过程中也一定使用过它吧?至少在在以下两种情况下,大家可以考虑使用策略模式,
几个类的主要逻辑相同,只在部分逻辑的算法和行为上稍有区别的情况。
有几种相似的行为,或者说算法,客户端需要动态地决定使用哪一种,那么可以使用策略模式,将这些算法封装起来供客户端调用。
&&&&&& 策略模式是一种简单常用的模式,我们在进行开发的时候,会经常有意无意地使用它,一般来说,策略模式不会单独使用,跟模版方法模式、工厂模式等混合使用的情况比较多。
&大粒度的 if --else if...可以使用 工厂+策略模式搞定。
阅读(...) 评论()

我要回帖

更多关于 抽象的原则是什么 的文章

 

随机推荐