工厂模式:主要用来实例化有共同接口的类,工厂模式可以动态决定应该实例化那一个类。
工厂模式的形态
工厂模式主要用一下几种形态:
1:简单工厂(Simple Factory):不利于产生系列产品
2:工厂方法(Factory Method):又称为多形性工厂
3:抽象工厂(Abstract Factory):又称为工具箱,产生产品族,但不利于产生新的产品
一:简单工厂模式
简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存在的目的很简单:定义一个用于创建对象的接口。
在简单工厂模式中,一个工厂类处于对产品类实例化调用的中心位置上,它决定那一个产品类应当被实例化, 如同一个交通警察站在来往的车辆流中,决定放行那一个方向的车辆向那一个方向流动一样。
先来看看它的组成:
1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑。在java中它往往由一个具体类实现。
2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。在java中由接口或者抽象类来实现。
3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
简单工厂模式简单实现:
这里我们用生产电脑来举例,假设有一个电脑的代工生产商,它目前已经可以代工生产联想电脑了,随着业务的拓展,这个代工生产商还要生产惠普和华硕的电脑,这样我们就需要用一个单独的类来专门生产电脑,这就用到了简单工厂模式。下面我们来实现简单工厂模式:
创建抽象产品类
我们创建一个电脑的抽象产品类,他有一个抽象方法用于启动电脑:
public abstract class Computer {
/**
* 产品的抽象方法,由具体的产品类去实现
*/
public abstract void start();
}
创建具体产品类
接着我们创建各个品牌的电脑,他们都继承了他们的父类Computer ,并实现了父类的start方法:
联想电脑:
public class LenovoComputer extends Computer{
@Override
public void start() {
System.out.println("联想电脑启动");
}
}
惠普电脑:
public class HpComputer extends Computer{
@Override
public void start() {
System.out.println("惠普电脑启动");
}
}
华硕电脑:
public class AsusComputer extends Computer {
@Override
public void start() {
System.out.println("华硕电脑启动");
}
}
创建工厂类
接下来创建一个工厂类,它提供了一个静态方法createComputer用来生产电脑。你只需要传入你想生产的电脑的品牌,它就会实例化相应品牌的电脑对象:
public class ComputerFactory {
public static Computer createComputer(String type){
Computer mComputer=null;
switch (type) {
case "lenovo":
mComputer=new LenovoComputer();
break;
case "hp":
mComputer=new HpComputer();
break;
case "asus":
mComputer=new AsusComputer();
break;
}
return mComputer;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
客户端调用工厂类
客户端调用工厂类,传入“hp”生产出惠普电脑并调用该电脑对象的start方法:
public class CreatComputer {
public static void main(String[]args){
ComputerFactory.createComputer("hp").start();
}
}
二、工厂方法模式
工厂方法模式定义
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
接上边的例子:
其中创建抽象产品和创建具体产品是一样的。
创建抽象工厂:里面有一个createComputer方法,想生产哪个品牌的电脑就生产那个:
public abstract class ComputerFactory {
public abstract <T extends Computer> T createComputer(Class<T> clz);
}
具体工厂
广达代工厂是一个具体的工厂,他继承抽象工厂,通过反射来生产不同厂家的电脑:
/**
* 广达代工厂
*/
public class GDComputerFactor extends ComputerFactory {
@Override
public <T extends Computer> T createComputer(Class<T> clz) {
Computer computer=null;
String classname=clz.getName();
try {
computer= (Computer) Class.forName(classname).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return (T) computer;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
客户端调用:
public class Client {
public static void main(String[]args) {
ComputerFactory computerFactory = new GDComputerFactor();
LenovoComputer mLenovoComputer=computerFactory.createComputer(LenovoComputer.class);
mLenovoComputer.start();
HpComputer mHpComputer=computerFactory.createComputer(HpComputer.class);
mHpComputer.start();
AsusComputer mAsusComputerr=computerFactory.createComputer(AsusComputer.class);
mAsusComputerr.start();
}
}
工厂方法与简单工厂
简单工厂模式我们都知道,在工厂类中包含了必要的逻辑判断,根据不同的条件来动态实例化相关的类,对客户端来说,去除了与具体产品的依赖,与此同时也会带来一个问题:如果我们去增加产品,比如我们要生产苹果电脑,那我们就需要在工厂类中在添加一个Case分支条件,这违背了开放封闭原则,我们对修改也开放了,不理解开放封闭的原则的同学可以查看设计模式(一)设计六大原则 这篇文章。而工厂方法模式就没有违背这个开放封闭原则,如果我们需要生产苹果电脑,并不需要去修改工厂类,直接创建产品就好了。
三、抽象工厂模式
抽象工厂模式定义
为创建一组相关或者相互依赖的对象提供一个接口,而无需指定它们的具体类。
抽象工厂模式简单实现
联想和惠普生产的电脑分为了两个产品线,一个台式机,一个是笔记本。为了解决增加产品线的问题,我们用抽象工厂模式来进行实现。
抽象产品
首先定义抽象产品类:
public abstract class DesktopComputer {
public abstract void start();
}
public abstract class NotebookComputer {
public abstract void start();
}
两个抽象产品类分别为DesktopComputer和NotebookComputer ,用来定义两个产品线:台式机和笔记本。它们都定义了start方法,用来启动电脑。
具体产品
具体产品为联想和惠普旗下的台式机和笔记本,如下所示。
public class LenovoDesktopComputer extends DesktopComputer {
@Override
public void start() {
System.out.println("联想台式电脑启动");
}
}
public class HpDesktopComputer extends DesktopComputer {
@Override
public void start() {
System.out.println("惠普台式电脑启动");
}
}
public class LenovoNotebookComputer extends NotebookComputer {
@Override
public void start() {
System.out.println("联想笔记本电脑启动");
}
}
public class HpNotebookComputer extends NotebookComputer {
@Override
public void start() {
System.out.println("惠普笔记本电脑启动");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
抽象工厂
接着创建生产电脑的抽象工厂,如下所示,
public abstract class ComputerFactory {
public abstract DesktopComputer createDesktopComputer();
public abstract NotebookComputer createNotebookComputer();
}
定义了两个方法,分别用来生产台式电脑和笔记本电脑。
具体工厂
定义联想和惠普工厂:
public class LenovoFactory extends ComputerFactory {
@Override
public DesktopComputer createDesktopComputer() {
return new LenovoDesktopComputer();
}
@Override
public NotebookComputer createNotebookComputer() {
return new LenovoNotebookComputer();
}
}
public class HpFactory extends ComputerFactory {
@Override
public DesktopComputer createDesktopComputer() {
return new HpDesktopComputer();
}
@Override
public NotebookComputer createNotebookComputer() {
return new HpNotebookComputer();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
联想工厂和惠普工厂用来生产台式机和笔记本这两个不同产品线的电脑。
客户端调用
最后编写客户端:
public class Client {
public static void main(String[]args) {
ComputerFactory lenocoFactory=new LenovoFactory();
lenocoFactory.createDesktopComputer().start();
lenocoFactory.createNotebookComputer().start();
ComputerFactory hpFactory=new HpFactory();
hpFactory.createDesktopComputer().start();
hpFactory.createNotebookComputer().start();
}
}
分别用LenovoFactory和HpFactory生产台式和笔记本电脑,并调用start方法启动它们。
抽象工厂模式的使用场景
一个系统不依赖于产品线实例如何被创建、组合和表达的细节。
系统中有多于一个的产品线,而每次只使用其中某一产品线。
一个产品线(或是一组没有任何关系的对象)拥有相同的约束。