之前写过一篇关于工厂模式(Factory Pattern)的随笔,里面分析了简单工厂模式,但对于工厂方法和抽象工厂的分析较为简略。这里重新分析分析三者的区别,工厂模式是java设计模式中比较简单的一个设计模式,但很多地方都用到了工厂模式,(如解析xml中,jdbc连接数据库等)利用好工厂模式对程序的设计很有用处。工厂模式在一些设计模式的书中分为简单工厂模式,工厂方法模式和抽象工厂模式三类。也有把工厂方法模式划分到抽象工厂模式的,认为工厂方法是抽象工厂模式的特例的一种,就是只有一个要实现的产品接口。下面结合例子分析三者的区别。

  首先是简单工厂模式,这里以工厂生产产品为例。

产品类的共同接口

 1 package factory;
2 /**
3 *
4 * @author CIACs
5 *
6 */
7 public interface Product {
8 //声明类所需继承的共同接口,也可以是抽象类
9 }

产品A

 package factory;
/**
*
* @author CIACs
*
*/
public class ProductA implements Product {
public ProductA() {
System.out.println("ProductA");
}
}

产品B

 package factory;
/**
*
* @author CIACs
*
*/
public class ProductB implements Product {
public ProductB() {
System.out.println("ProductB");
}
}

工厂类

 package factory;
/**
*
* @author CIACs
*
*/
public class Factory {
//可以在工厂类中添加任何你所需要的逻辑
public static Product create(String str)
{
//生成ProductA
if(str.equalsIgnoreCase("ProductA"))
{
return new ProductA();
}
else
//生成ProductB
if(str.equalsIgnoreCase("ProductB"))
{
return new ProductB();
}
return null;
} }

客户端

 package factory;
/**
*
* @author CIACs
*
*/
public class Client {
public static void main(String[] args) {
//调用Factory的静态方法生成所要的类
Factory.create("productA");
Factory.create("ProductB");
}
}

控制台输出结果:

简单工厂模式实现了生成产品类的代码跟客户端代码分离,在工厂类中你可以添加所需的生成产品的逻辑代码,但是问题来了,优秀的java代码是符合“开放-封闭”原则的,也就是说对扩展开发,对修改关闭,如果你要加一个产品类C,你就要修改工厂类里面的生成产品的代码,在这里你就要增加if-else判断。对于这个问题,我们的工厂方法模式就可以解决这个问题。

  接下来是工厂方法模式

产品类中增加了ProductC(其他产品类的代码是可以重用上面的,只要把包名更改了就行)。

 package factoryMehtod;
/**
*
* @author CIACs
*
*/ public class ProductC implements Product {
public ProductC() {
System.out.println("productC");
}
}

声明工厂接口

 package factoryMehtod;
/**
*
* @author CIACs
*
*/
public interface Factory {
//声明产生产品类的方法
public Product createProduct();
}

产生ProductA的FactoryA

 package factoryMehtod;
/**
*
* @author CIACs
*
*/
public class FactoryA implements Factory {
//实现工厂类的方法生成产品类A
public Product createProduct()
{
return new ProductA();
} }

产生ProductB的FactoryB

 package factoryMehtod;
/**
*
* @author CIACs
*
*/
public class FactoryB implements Factory {
//实现工厂类的方法生成产品类B
public Product createProduct()
{
return new ProductB();
}
}

产生ProductC的FactoryC

 package factoryMehtod;
/**
*
* @author CIACs
*
*/
public class FactoryC implements Factory {
//实现工厂类的方法生成产品类C
public Product createProduct()
{
return new ProductC();
}
}

客户端

 package factoryMehtod;
/**
*
* @author CIACs
*
*/
public class Client {
public static void main(String[] args) {
Factory factory;
factory = new FactoryA();
factory.createProduct();
factory = new FactoryB();
factory.createProduct();
factory = new FactoryC();
factory.createProduct();
}
}

控制台输出结果:

  工厂方法模式中我们把生成产品类的时间延迟,就是通过对应的工厂类来生成对应的产品类,在这里我们就可以实现“开发-封闭”原则,无论加多少产品类,我们都不用修改原来类中的代码,而是通过增加工厂类来实现。但是这还是有缺点的,如果产品类过多,我们就要生成很多的工厂类。假如我们要实现的产品接口不止一个,也就是有多个产品接口,不同产品接口有对应的产品族。什么是产品族呢?简单的理解就是,不同牌子产的车里面会有跑车类型,家庭类型,商用类型等的车,不同牌子的车的跑车类型的车可以组成一个产品族。对于这种情况我们可以采用抽象工厂模式。

   最后是抽象工厂模式,在这里我们为不同产品附加上对应的礼物,就是说ProductA中会有GiftA。

增加的Gift接口

 package abstractFactory;
/**
*
* @author CIACs
*
*/
public interface Gift {
//声明产品赠品的接口,当然也可以是抽象类,同样为了简单就不声明方法了
}

GiftA类

 package abstractFactory;
/**
*
* @author CIACs
*
*/
public class GiftA implements Gift {
public GiftA()
{
System.out.println("GiftA");
}
}

GiftB类

 package abstractFactory;
/**
*
* @author CIACs
*
*/
public class GiftB implements Gift {
public GiftB()
{
System.out.println("GiftB");
}
}

Factory接口

 package abstractFactory;
/**
*
* @author CIACs
*声明Product类工厂和Gift类工厂的工同工厂接口
*/
public interface Factory {
public Product createProduct();
public Gift createGift(); }

生成ProductA和GiftA的FactoryA

 package abstractFactory;
/**
*
* @author CIACs
*FactoryA可以生成ProductA和GiftA
*/
public class FactoryA implements Factory {
@Override
public Product createProduct()
{
return new ProductA();
}
@Override
public Gift createGift()
{
return new GiftA();
}
}

生成ProductB和GiftB的FactoryB

 package abstractFactory;
/**
*
* @author CIACs
*FactoryB可以生成ProductB和GiftB
*/
public class FactoryB implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
@Override
public Gift createGift() {
return new GiftB();
} }

客户端

 package abstractFactory;
/**
*
* @author CIACs
*
*/
public class Client {
public static void main(String[] args) {
Factory factory;
factory = new FactoryA();
factory.createProduct();
factory.createGift();
factory = new FactoryB();
factory.createProduct();
factory.createGift();
}
}

控制台输出结果:

  抽象工厂模式中我们可以定义实现不止一个接口,一个工厂也可以生成不止一个产品类,抽象工厂模式较好的实现了“开放-封闭”原则,是三个模式中较为抽象,并具一般性的模式。我们在使用中要注意使用抽象工厂模式的条件。

由于水平有限,文章中难免有错误的地方,欢迎指出错误或不足之处,共同进步。欢迎转载,谢谢

简单工厂模式&工厂方法模式&抽象工厂模式的区别的更多相关文章

  1. Java设计模式---工厂模式(简单工厂、工厂方法、抽象工厂)

    工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory M ...

  2. 设计模式(Python)-简单工厂,工厂方法和抽象工厂模式

    本系列文章是希望将软件项目中最常见的设计模式用通俗易懂的语言来讲解清楚,并通过Python来实现,每个设计模式都是围绕如下三个问题: 为什么?即为什么要使用这个设计模式,在使用这个模式之前存在什么样的 ...

  3. 设计模式3---工厂模式(Factory Pattern简单工厂、工厂方法、抽象工厂)

    工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类.工厂模式的形态工厂模式主要用一下几种形态:1:简单工厂(Simple Factory).2:工厂方法(Factory M ...

  4. Java设计模式之简单工厂、工厂方法和抽象工厂

    在前面的学习中(参见前面的博客),我们学到了很多OO原则: 封装变化 多用组合,少用继承 针对接口/超类编程,不针对实现编程 松耦合 开闭原则 让我们从一个简单的类开始,看看如何将之改造成符合OO原则 ...

  5. 简单工厂 VS 工厂方法 VS 抽象工厂

    说到设计模式.自然少不了简单工厂模式.工厂方法和抽象工厂这三姐妹. 它们之间可谓是各有所长,术业专攻啊!这篇博客来简单的梳理一下三者之间的关系. 那么工厂又是什么意思呢?结合三者的特点,我觉得能够这样 ...

  6. headfirst设计模式(5)—工厂模式体系分析及抽象工厂模式

    先编一个这么久不写的理由 上周我终于鼓起勇气翻开了headfirst设计模式这本书,看看自己下一个设计模式要写个啥,然后,我终于知道我为啥这么久都没写设计模式了,headfirst的这个抽象工厂模式, ...

  7. c# 设计模式 之:简单工厂、工厂方法、抽象工厂之小结、区别

    很多时候,我发现这三种设计模式难以区分,常常会张冠李戴闹了笑话.很有必要深入总结一下三种设计模式的特点.相同之处和不同之处. 1 本质 三个设计模式名字中都含有“工厂”二字,其含义是使用工厂(一个或一 ...

  8. Java 工厂模式(一)— 抽象工厂(Abstract Factory)模式

    一.抽象工厂模式介绍: 1.什么是抽象工厂模式: 抽象工厂模式是所有形态的工厂模式中最为抽象和最具有一般性的一种形态,抽象工厂模式向客户端提供一个接口,使得客户端在不知道具体产品的情类型的情况下,创建 ...

  9. head first 设计模式笔记4-工厂模式(简单工厂、工厂方法、抽象工厂)

    1.简单工厂模式 Pizza public abstract class Pizza { abstract void prepare(); abstract void bake(); abstract ...

  10. FactoryMethod工厂方法模式升级成AbstractFactory抽象工厂模式

    具体参考抽象工厂(AbstractFactory)模式-创建型模式,本文在FactoryMethod工厂方法模式(创建型模式)的基础上进行业务进一步抽象,不做详细原理介绍. 1.在FactoryMet ...

随机推荐

  1. 通过构建Cocoapods私有库进行组件化开发探索

    专题一 一.创建私有索引库 选Github或者码云都可以,本例以Github为例.创建私有索引库用来作为自己组件库的索引: 二.本地添加私有索引库 添加:pod repo add 索引库名称 索引库地 ...

  2. 【LeetCode刷题Java版】Reverse Words in a String

    Given an input string, reverse the string word by word. For example, Given s = "the sky is blue ...

  3. Cocos2d-x3.1下 Android,APK自己主动升级

    项目要做Android的自己主动升级,对于我们之前做iOS的转Cocos开发做Android方面的功能..... 不正确说了.这里记录下我的实现过程. 原文地址:http://blog.csdn.ne ...

  4. Android框架之高速开发框架xUtil

    做Android开发我们通常是从原生态的開始,就是调用默认那些Android代码来开发我们的应用,可是到了一定程度,我们就想着怎么来高速开发我们的应用.这个时候我们就要着手来研究框架了. 以下介绍一个 ...

  5. [办公自动化]PPT文件太大,如何压缩?

    如果你经常需要制作PPT,文件太大的确是个问题. 那么应该如何压缩呢? 以office 2007为例 第一.可以选中图片,然后双击,在弹出的菜单栏中,选择压缩图片. 然后选择选项, 有三种比例可选,建 ...

  6. the “identity” of an object

    2. Built-in Functions — Python 3.6.5 documentation https://docs.python.org/3.6/library/functions.htm ...

  7. Ubuntu利用TCP协议来获取server时间

    Linux利用TCP协议来获取server时间 这里使用Unix网络编程里面的一个小程序,该client建立一个到server的TCP连接,然后读取由server以直观可读格式简单地送回的当前时间和日 ...

  8. bzoj2521

    最小生成树+最小割 ...我太zz了,没看出来全体减1是一个加1,看见后就是sb题了... 我们发现根据克鲁斯卡尔的过程,我们把边从小到大加入,如果两点已经相连就跳过,那么我们把所有小于等于这条边的边 ...

  9. end()与andSelf()

    end() 回到最近的一个"破坏性"操作之前.即,将匹配的元素列表变为前一次的状态. 如 果之前没有破坏性操作,则返回一个空集.所谓的"破坏性"就是指任何改变所 ...

  10. sqlserver2005连接失败,不存在或拒绝访问

    sqlserver2005连接失败,不存在或拒绝访问 启动tcp/ip连接的方法: 打开 /Microsoft SQL Server 2005/配置工具/目录下的SQL Server Configur ...