文档章节

Java设计模式之工厂方法模式与抽象工厂模式

木木匠
 木木匠
发布于 2018/11/09 14:39
字数 2325
阅读 16
收藏 1

一、前期回顾

上一篇《Java设计模式之单例模式》详细介绍了单例模式,介绍了单例模式的使用场景,优缺点,同时也写了两种常见的单例模式写法,懒汉式单例模式和饿汉氏单例模式,当然,单例模式的写法还有很多,比如,枚举单例模式,静态内部类单例模式等。有兴趣的可以自行查找资料。本篇开始介绍单例模式的第二篇,工厂方法模式,以及工厂模式的升级版,抽象工厂模式。

二、工厂方法模式的定义与实践

定义:Define an interface for creating an object,but let subclasses decide which class to instantiation.Factory Mehod lets a class defer instantiation to subclasses.翻译过来就是,定义一个用于创建对象的接口,让其子类决定实例化哪个类。工厂方法让一个类的实例化延迟到其子类。

上面的定义说明好像很绕口,如果不理解没关系,我们用个例子来说明这个定义:

//定义产品接口
public interface Iproduct {
    public void doSomething();
}
//产品实现类
public class ProductA implements Iproduct {
    @Override
    public void doSomething() {
        System.out.println("我是产品A,我可以搞事情");
    }
}
//定义工厂类接口
public interface IFactory {
    //创建产品工厂方法
    < T extends Iproduct> T creatProduct(Class<T> clz);
}
//工厂方法实现类
public class ProductFactory implements IFactory {
    @Override
    public <T extends Iproduct> T creatProduct(Class<T> clz) {
        Iproduct product=null;
        try {
            product= clz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}
//场景类
public class Client {
    public static void main(String[] args) {
        IFactory factory=new ProductFactory();
        Iproduct product= factory.creatProduct(ProductA.class);
        product.doSomething();
    }
}

上述例子,实现了一个简单的工厂方法模式,定义了一个工厂接口类,然后具体的工厂方法实现了创建对象的逻辑。看到这里,有人肯定会问,这里要new一个工厂类的实例,和我new一个具体的对象有什么区别呢?反正都要自己new,干嘛要搞一个工厂类这么绕呢?对,没错。这里是要new一个工厂类,但是上面的例子创建产品的对象是比较简单,所以感觉不出来,如果ProductA的实例创建是一个非常复杂的过程,那么这个时候我通过工厂方法模式创建对象的实例就很方便了。

肯定还有人问,我觉得上面这个方式还有点啰嗦,有没有更简便的方式实现工厂模式呢?答案是,有。我们接下来看看简单工厂模式。简单工厂方法模式就是上述工厂方法模式的简单版本。我们只要把上述工厂类的接口去掉,然后把工厂实现类改为静态类就可以实现简单工厂方法模式了。代码是这样的:

//这里只去掉了接口,改为静态方法
public class ProductFactory  {
    public static <T extends Iproduct> T creatProduct(Class<T> clz) {
        Iproduct product=null;
        try {
            product= clz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (T) product;
    }
}

public class Client {
    public static void main(String[] args) {
        Iproduct product= ProductFactory.creatProduct(ProductA.class);
        product.doSomething();
    }
}

这里就不用自己去new 工厂类啦,代码也简洁了很多。但是去掉了接口也就意味着后面的扩展是不友好的,所以违反了开闭原则。

三、抽象工厂模式的定义与实践

定义:Provide an interface for creating families of related or dependent objects without specifying their concrete classes.翻译: 提供一个创建相关或者相互依赖的对象的接口,并且无需指定他们的具体实现类。

这里理解可能有点困难,为了便于理解,我们先引入两个概念。

产品等级结构: 产品等级结构即产品的继承结构,如一个抽象类是汽车,其子类就是各个品牌的汽车,比如奔驰,宝马汽车。汽车和奔驰就构成了一个产品等级结构,抽象汽车是父类,而具体品牌的汽车是其子类。

产品族 : 在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如奔驰工厂生产的奔驰跑车,宝马公司生产的跑车,奔驰跑车位于奔驰产品等级结构中,宝马跑车位于宝马产品等级结构中。

所以,汽车和品牌是一个产品等级结构,而每个品牌下面有多个产品线,也就是说奔驰牌下面的汽车有多个产品族,比如跑车族,SUV族。奔驰跑车和宝马跑车是一个产品族,奔驰SUV和宝马SUV是一个产品族。所以上面定义中“相关或者相互依赖的对象”就是场景中包含,同一个等级结构中有不同的产品族。 ,我们来用一个实际场景来说明下。

假设,我需要一个汽车工厂,汽车可以生产跑车和SUV车型,那么这个时候用之前的工厂方法模式就不满足了,方法工厂模式只能满足生产一个产品,现在需要生产两个产品。所以我们在方法工厂模式的基础上改造下来满足这个场景。

//汽车接口
public interface ICar {
     void dirver();
}
//抽象汽车类
public abstract class AbstractProduct implements ICar{
    @Override
    public void dirver() {
        System.out.println("我是汽车,我可以开动");
    }

    /***
     * 展示不同车的亮点*/
    public abstract void showSpecial();
}
//宝马SUV实现类
public class BmwSuv extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是宝马牌SUV,我的特点就是多功能用途");
    }
}
//宝马跑车实现类
public class BmwProductRoadster extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是宝马跑车,我的特点就是跑的快");
    }
}
//奔驰SUV
public class BenzSuv extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是奔驰牌SUV,我的特点就是多功能用途");
    }
}
//奔驰跑车
public class BenzProductRoadster extends AbstractProduct {
    @Override
    public void showSpecial() {
        System.out.println("我是奔驰跑车,我的特点就是跑的快");
    }
}

//抽象工厂类
public abstract class AbstractFactory {
    //创建跑车
    public abstract < T extends ICar> T createRoadster();
    //创建SUV
    public abstract < T extends ICar> T createSuv();
}
//奔驰汽车工厂类
public class BenzFactory extends AbstractFactory {
    @Override
    public <T extends ICar> T createRoadster() {
        return (T) new BenzProductRoadster();
    }

    @Override
    public <T extends ICar> T createSuv() {
        return (T) new BenzSuv();
    }
}
//宝马汽车工厂类
public class BmwFactory extends AbstractFactory {
    @Override
    public <T extends ICar> T createRoadster() {
        return (T) new BmwProductRoadster();
    }

    @Override
    public <T extends ICar> T createSuv() {
        return (T) new BmwSuv();
    }
}
//场景类
public class Client {
    public static void main(String[] args) {
        AbstractFactory bmwFactory=new BmwFactory();
        AbstractFactory benzFactory=new BenzFactory();
        AbstractProduct bmwRoadster= bmwFactory.createRoadster();
        AbstractProduct bmwSuv=bmwFactory.createSuv();
        AbstractProduct benzRoadster=benzFactory.createRoadster();
        AbstractProduct benzSuv=benzFactory.createSuv();
        bmwRoadster.showSpecial();
        bmwSuv.showSpecial();
        benzRoadster.showSpecial();
        benzSuv.showSpecial();
    }
}

细心的读者应该发现,我们的改造相对于工厂方法模式而言,只是抽象工厂模式新增了多一个创建方法。这也是抽象工厂模式和工厂方法模式最明显的区别,抽象工厂模式可以满足多类型,多业务的场景,比如汽车工厂可以生产多种类型汽车,就适用于抽象工厂模式。而普通工厂方法模式就是针对生产某一种对象而言比较适用。总结来说就是,抽象工厂模式适用于多产品族的情况,普通工厂方法模式适用于单产品族情况。

四、总结

上面介绍了工厂方法模式与抽象工厂模式的定义与实践,同时也衍生了一个简单工厂模式。我们先来总结下工厂模式的优点与缺点。

优点:

1.良好的封装性,代码结构清晰,不用关注具体对象的创建过程,符合迪米特法则。

2.良好的扩展性,我们扩展了产品,只要新建对应的工厂类,实现自己的实现逻辑即可。

缺点:

1.对于抽象工厂模式,产品族的扩展比较困难,需要修改顶部抽象工厂类,这会导致所有实现类都要修改,不符合开闭原则。

2.对于简单工厂模式,由于没有接口和抽象父类的约束,从而也会导致扩展只能修改代码,不符合开闭原则。

最后我们列一个表格来总结下工厂方法模式,简单工厂模式,抽象工厂模式的区别。

简单工厂模式工厂方法模式抽象工厂模式
有无接口或抽象类
适用场景一般不涉及扩展,单产品族涉及单产品族,便于扩展多产品族场景,可以扩展等级结构,不便于扩展产品族
实现复杂度最简单简单一般

五、参考

《设计模式之禅》

设计模式(三)抽象工厂模式

六、推荐阅读

Java设计模式之单例模式

JAVA设计模式之开篇

带你走进java集合之ArrayList

带你走进java集合之HashMap

Java锁之ReentrantLock(一)

Java锁之ReentrantLock(二)

Java锁之ReentrantReadWriteLock

© 著作权归作者所有

木木匠
粉丝 105
博文 30
码字总数 65486
作品 0
广州
高级程序员
私信 提问
简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别

转载:原地址http://www.cnblogs.com/zhangchenliang/p/3700820.html 简单工厂、工厂方法、抽象工厂、策略模式、策略与工厂的区别 结合简单示例和UML图,讲解工厂模式简单原理。 一、引子 话说...

法斗斗
2018/05/08
245
0
设计模式15——Template Method设计模式

Template Method模板方法设计模式定义一个操作中算法的骨架,将具体步骤的执行延迟到子类中实现。Java中的抽象类就是使用了模板方法设计模式。模板方法设计模式结构如下: 以文档处理为例,T...

小米米儿小
2014/01/24
201
0
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
269
0
PHP设计模式(一):简介及创建型模式

我们分三篇文章来总结一下设计模式在PHP中的应用,这是第一篇创建型模式。 一、设计模式简介 首先我们来认识一下什么是设计模式: 设计模式是一套被反复使用、容易被他人理解的、可靠的代码设...

juhenj
2014/05/15
273
2
设计模式: Java中的工厂设计模式

原文链接 https://github.com/shellhub/blog/issues/22 前言 工厂设计模式(Factory Design Pattern)属于创建模式之一,工厂设计模式在JDK,Spring,Stuts被广泛使用 当一个类或者接口有多个子类...

shellhub
2018/08/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

作为一个(IT)程序员!聊天没有话题?试试这十二种技巧

首先呢?我是一名程序员,经常性和同事没话题。 因为每天都会有自己的任务要做,程序员对于其他行业来说;是相对来说比较忙的。你会经常看到程序员在发呆、调试密密麻麻代码、红色报错发呆;...

小英子wep
今天
12
0
【SpringBoot】产生背景及简介

一、SpringBoot介绍 Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程,该框架使用了特定的方式来进行配置,从而使开发人员不再需要...

zw965
今天
4
0
简述并发编程分为三个核心问题:分工、同步、互斥。

总的来说,并发编程可以总结为三个核心问题:分工、同步、互斥。 所谓分工指的是如何高效地拆解任务并分配给线程,而同步指的是线程之间如何协作,互斥则是保证同一时刻只允许一个线程访问共...

dust8080
今天
6
0
OSChina 周四乱弹 —— 当你简历注水但还是找到了工作

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @花间小酌 :#今日歌曲推荐# 分享成龙的单曲《男儿当自强》。 《男儿当自强》- 成龙 手机党少年们想听歌,请使劲儿戳(这里) @hxg2016 :刚在...

小小编辑
今天
3.3K
22
靠写代码赚钱的一些门路

作者 @mezod 译者 @josephchang10 如今,通过自己的代码去赚钱变得越来越简单,不过对很多人来说依然还是很难,因为他们不知道有哪些门路。 今天给大家分享一个精彩的 GitHub 库,这个库整理...

高级农民工
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部