搞定Java工厂模式
Posted lzy_tinyjoy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搞定Java工厂模式相关的知识,希望对你有一定的参考价值。
简述:
工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。简单的说,工厂模式能够帮助我们轻松方便地构造对象实例,而不必关心构造对象实例的细节和复杂过程。 分类: 工厂模式可以分为简单工厂、工厂方法和抽象工厂。这篇博文一一介绍一下。简单工厂:
简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式(Static FactoryMethod Pattern),是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类(或者父接口)。 举个例子,以手机为例,目前流行的有三星与苹果手机,手机的基本功能就是拨打电话,那么首先对手机进行抽象,然后三星手机与苹果手机是具体的手机实现类。然后创建一个手机工厂去生产手机。OK,接下来以这个为例实现简单工厂模式。UML图:
实例:
首先创建接口Mobile:使用接口暴露公共的方法,使用类来提供公共的实现public interface Mobile
String call();
具体产品实现类如下:
public class AppleMobile implements Mobile
private String call;
public AppleMobile()
call = "苹果手机拨打电话";
System.out.println("Apple手机生产完毕!");
@Override
public String call()
return call != null ? call : null;
public class SamsungMobile implements Mobile
private String call;
public SamsungMobile()
call = "三星手机拨打电话";
System.out.println("Samsung手机生产完毕!");
@Override
public String call()
return call != null ? call : null;
这些功能类似的类的实例化成为了一个问题,每次 new 对象很麻烦,封装成简单工厂模式。
public class MobileFactory
public static final int APPLE = 1;
public static final int SAMSUNG = 2;
public static Mobile getMobile(int type)
if (APPLE == type)
return new AppleMobile();
else if (SAMSUNG == type)
return new SamsungMobile();
else
throw new IllegalArgumentException();
简单工厂模式所涉及的这个角色我们已经创建完成,接下来我们使用客户端测试一下:
public class Client
public static void main(String[] args)
AppleMobile mobile = (AppleMobile)MobileFactory.getMobile(MobileFactory.APPLE);
SamsungMobile samsungMobile = (SamsungMobile) MobileFactory.getMobile(MobileFactory.SAMSUNG);
经过上述的案例我们已经基本掌握了简单工厂模式,那现在思考一个问题,假如现在业务增加,需要生产华为手机,我们就要再创建一个再创建一个HuaweiMobile类,接下来再修改MobileFactory类,或者我们要对AppleMobile以及SamsungMobile做些业务上的变更,那么我们还要去修改AppleMobile或者SamsungMobile。如果说项目的业务非常简单我们做一些简单的修改也无妨,但是如果项目已经成熟且有些复杂,这时候再做修改就不那么简单了。所以这个问题也暴露出简单工厂模式的一个弊端:简单工厂模式不利于拓展,违背了“开闭原则 ”,每次添加一个类,都要去修改工厂类。所以此时“工厂方法模式”利剑出鞘。
工厂方法模式
工厂方法模式其原理就是对简单工厂模式也进行抽象。更具体的说就是对简单工厂模式中的工厂类与产品类再进一步封装。还以上述的例子为例继续工厂方法模式。工厂方法模式UML:
实例解析:
我们基于简单工厂的上述案例继续封装。我们知道工厂方法模式只是对简单工厂模式中工厂类的进一步抽象。接下来我们首先给出MobileFactory 的封装接口。public interface MobileFactory
public Mobile getMobile();
然后我们再看一下AppleFactory 和SamsungFactory 类:
public class AppleFactory implements MobileFactory
@Override
public Mobile getMobile()
return new AppleMobile();
public class SamsungFactory implements MobileFactory
@Override
public Mobile getMobile()
return new SamsungMobile();
OK,到此一个基本的工厂方法模式也已经创建完毕,刚才已经说了工厂方法模式是为了解决简单工厂模式不符合“开闭原则”而产生的。那么现在我们添加一个生产华为手机的业务,UML图如下:
OK,从UML图看出再增加Huawei手机业务不需要修改代码了,这样完美解决了简单工厂不能实现“开闭原则”的弊端。我们再思考一个问题,如果此时我们还需要手机充分电器,每种手机都需要自己的手机充电器,此时我们需要怎么做呢?如果继续采用工厂方法模式那么则需要再创建手机充电器工厂,那么这样的话每种产品需要创建一个工厂类,两种手机需要创建两个手机充电器工厂类,这样一来代码变得非常的冗余。我们再仔细想一下,每种手机和手机手机充电器存在着相互依赖的关系,我们有必要再去创建一个相应的工厂类吗?确实是这样,这就是抽象工厂模式。简单来说,可以把有一些有联系或者相近的产品,放到一个工厂去生产,没有必要单独再开一个工厂了。 现在就让我们认识一下抽象工厂模式吧!
抽象工厂模式
抽象工厂模式是工厂方法模式的升级版本,设计模式中抽象工厂原文:"Provide an interface for creating families of related or dependent objects without specifying their concrete classes",意思是“为创建一组相关或相互依赖的对象提供一个接口,无需指定它们的具体类”。在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。 举个例子,我们购买手机时都会包含两样基本的东西:手机和手机充电器。那么我们将手机视作一种产品Mobile,将手机充电器Charger视作另一种产品,我们都知道它们二者具有相互依赖的关系,我们将其视作一个产品族。目前流行的手机有苹果和三星(虽然受Note7爆砸门的影响,但三星手机依然是手机界的老大哥),那么可以看做是两个产品族。然后我们再抽象出工厂类MobileFactory,该工厂类用于生产一个产品族(也即是生产手机和手机充电器),最后再根据Apple手机和Samsung手机分别创建两个具体工厂类AppleFactory和SamsungFactory用于生产Apple手机和Apple充电器以及Samsung手机和Samsung手机充电器。OK,接下来我们就以这样一个背景为例实现一个简单的抽象工厂案例。UML图:
代码实现:
根据上述问题和UML图,首先抽象出第一个产品Mobile如下:/**
* 类描述:产品类Mobile
*
* @author lzy
*
*/
public interface Mobile
String getName();
然后具体产品类AppleMobile和SamsungMobile如下:
public class AppleMobile implements Mobile
private String name;
public AppleMobile()
name = "苹果手机";
System.out.println("Apple手机生产完毕!");
@Override
public String getName()
return name != null ? name : null;
public class SamsungMobile implements Mobile
private String name;
public SamsungMobile()
name = "三星手机";
System.out.println("Samsung手机生产完毕!");
@Override
public String getName()
return name != null ? name : null;
另一种产品手机手机充电器Charger和具体产品类AppleCharger以及SamsungCharger与Mobile类似,为了方面理解直接把代码贴出来:
/**
* 产品类:Charger
*
* @author lzy
*
*/
public interface Charger
String getName();
两个具体的charger:
public class AppleCharger implements Charger
private String name;
public AppleCharger()
name = "苹果手机充电器";
System.out.println("Apple手机充电器生产完毕!");
@Override
public String getName()
return name != null ? name : null;
public class SamsungCharger implements Charger
private String name;
public SamsungCharger()
name = "三星充电器";
System.out.println("Samsung手机充电器生产完毕!");
@Override
public String getName()
return name != null ? name : null;
OK,到此为止,两个产品族(每个产品族两种产品)构建完毕,接下来就来创建产品族对应的工厂。 要创建工厂我们需要就工厂进行抽象,那么具体该怎么抽象呢?那么让我们回到抽象工厂的描述:创建一组相关或相互依赖的对象。根据描述我们可以知道工厂就是用来创建一组相关产品的对象(也就是一个产品族的相对应的对象)。OK,考虑到每个产品族工厂要生产两种产品,所以对工厂进行如下抽象:
public interface MobileFactory
// 生产手机
Mobile getMobile();
// 生产充电器
Charger getCharger();
接下来就要创建具体工厂,AppleFactory生产苹果手机产品族对象,SamsungFactory生产三星手机产品族对象,具体代码实现如下:
public class AppleFactory implements MobileFactory
// 生产苹果手机
@Override
public Mobile getMobile()
return new AppleMobile();
// 生产苹果手机充电器
@Override
public Charger getCharger()
return new AppleCharger();
public class SamsungFactory implements MobileFactory
// 生产三星手机
@Override
public Mobile getMobile()
return new SamsungMobile();
// 生产三星手机充电器
@Override
public Charger getCharger()
return new SamsungCharger();
目前为止,我们的抽象工厂和具体工厂创建完毕,接下来写一个客户端调用一下:
public class Client
public static void main(String[] args)
AppleFactory appleFactory = new AppleFactory();
AppleMobile appleMobile = (AppleMobile) appleFactory.getMobile();
AppleCharger appleCharger = (AppleCharger) appleFactory.getCharger();
SamsungFactory samsungFactory = new SamsungFactory();
SamsungMobile samsungMobile = (SamsungMobile) samsungFactory.getMobile();
SamsungCharger samsungCharger = (SamsungCharger) samsungFactory.getCharger();
目前为止一个抽象工厂的案例全部完成,那么我们现在可以思考几个问题:①抽象工厂与工厂方法模式有什么区别 ②抽象工厂的优势在哪里? 抽象工厂与工厂方法模式的区别: 通过前面的案例我们可以看出他们的抽象工厂生产的产品不同,工厂方法模式中工厂生产的产品比较单一,换句话说工厂方法模式中生产的产品可能就是一个产品族(相对于抽象工厂来说)的一个产品,换成术语说就是生产的产品就是所谓的结构性产品。而抽象工厂生产的产品是一个产品族。 抽象工厂的优势在哪里? 我们在抽象工厂模式的开头就说:抽象工厂模式是工厂方法模式的升级版本。因此抽象工厂模式一样遵循“开闭原则”,同时抽象工厂中每个具体工厂类可以创建多个具体产品类的实例,所以相比工厂方法模式减少了产品工厂的创建。
结尾啦, 给自己也给大家一些工厂模式优化的Tips: ① 苹果手机有iPhone6、iPhone7,三星手机有Note系列、Galaxy系列等,如果考虑这些复杂因素产品类应该做进一步抽象。 ② 客户端调用的时候针对不同产品要做拆箱与装箱操作,这样一来使用不方便同时装箱与拆箱也比较耗时,所以在做产品抽象的时候可以添加泛型。
以上是关于搞定Java工厂模式的主要内容,如果未能解决你的问题,请参考以下文章