工厂模式分为工厂方法模式和抽象工厂模式;
工厂模式是解决产品等级的问题;
抽象工厂是解决产品族的问题。
现在我们先来说一下工厂模式:
工厂方法模式:
定义:定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
适用场景:
1.创建对象需要大量重复的代码
2.客户端不依赖与产品类实例如何被创建、实现等细节
3.一个类通过其子类来指定创建哪个对象
利用面向对象的多态性和里氏替换原则,我们可以使用工厂模式。
**优点:**
1.客户端只需关心所需产品的工厂,无需关系实现细节。
2.加入新产品符合开闭原则,提高可扩展性。
** 缺点: **
1.类的个数增多,增加复杂度
2.增加系统的抽象性和理解难度
下面我们来用coding来解释工厂方法的使用:
首先我们来创建各种电脑的父类:
/**
* @program: adpn-pattern->Computer
* @description: 电脑类
* @author: Jstar
* @create: 2019-11-17 11:18
**/
public abstract class Computer {
public abstract void process();
}
接下来我们来创建3个电脑父类的实现:
public class ThinkpadComputer extends Computer {
@Override
public void process() {
System.out.println("这里可写业务代码,但我们模拟--生产联想电脑");
}
}
public class MacbookComputer extends Computer {
@Override
public void process() {
System.out.println("这里可写业务代码,但我们模拟--生产苹果电脑");
}
}
public class HpComputer extends Computer {
@Override
public void process() {
System.out.println("这里可写业务代码,但我们模拟--生产惠普电脑");
}
}
创建电脑工厂的父类:
/**
* @program: adpn-pattern->ComputerFactory
* @description: 生产电脑工厂类
* @author: Jstar
* @create: 2019-11-17 11:34
**/
public abstract class ComputerFactory {
public abstract Computer getComputer();
}
创建 3个 电脑工厂子类的实现:
public class ThinkpadComputerFactory extends ComputerFactory {
@Override
public Computer getComputer() {
return new ThinkpadComputer ();
}
}
public class MacbookComputerFactory extends ComputerFactory {
@Override
public Computer getComputer() {
return new MacbookComputer();
}
}
public class HpComputerFactory extends ComputerFactory {
@Override
public Computer getComputer() {
return new HpComputer();
}
}
我们使用客户端来调用上面的工厂方法:
/**
* @program: adpn-pattern->Test
* @description: 测试类
* @author: Jstar
* @create: 2019-11-17 11:42
**/
public class Test {
public static void main(String[] args) {
ComputerFactory macbookComputerFactory = new MacbookComputerFactory();
ComputerFactory thinkpadComputerFactory = new ThinkpadComputerFactory();
ComputerFactory hpComputerFactory = new HpComputerFactory();
Computer macbookComputer = macbookComputerFactory.getComputer();
Computer thinkpadComputer = thinkpadComputerFactory.getComputer();
Computer hpComputer = hpComputerFactory.getComputer();
macbookComputer.process();
thinkpadComputer.process();
hpComputer.process();
}
}
看一下执行结果
这里可写业务代码,但我们模拟--生产苹果电脑
这里可写业务代码,但我们模拟--生产联想电脑
这里可写业务代码,但我们模拟--生产惠普电脑
至此,工厂方法模式演示完了,下面我们来看一下UML图:
再来查看一下调用链:
我们再来看一下工厂方法的定义:
定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行。
在此例中 ComputerFactory 就是一个工厂抽象类,具体的实现和实例化创建哪种类型都在 子类的 ThinkpadComputerFactory、MacbookComputerFactory、HpComputerFactory 中定义了。
下面我们来看一下,jdk中使用工厂方法的地方:
1.看一下 集合 Collection 中的 iterator() 这个方法:
我们发现有很多类重写这个方法:
那我们来看看熟悉的 ArrayList 是怎么重写的。
从图上我们可以看到,Collection 就是 抽象的工厂接口,具体的实现 是由像 ArrayList 这样的工厂实现类来实现的。
Collection 就像上面讲的ComputerFactory, ArrayList 就像 MacbookComputerFactory,
ArrayList 中 iterator() 方法返回的 Itr 类就是 就像具体生产出来的 MacbookComputer , 而 Itr 实现的 Iterator ,就像是 Computer 。
所以,Collection 集合中 iterator() 方法也有使用 工厂方法,具体的实现由ArrayList 这样的子类完成。
2.我们再来看一个例子:
LoggerFactory 的 getLogger() 方法:
public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
其中的 ILoggerFactory 是一个接口,定义了 getLogger(String var1) 方法,具体的 getLogger(String var1) 方法由子类实现。
public interface ILoggerFactory {
Logger getLogger(String var1);
}
子类 NOPLoggerFactory 实现了ILoggerFactory ,重写了 getLogger(String name) 方法,返回的 Logger 对象。
public class NOPLoggerFactory implements ILoggerFactory {
public NOPLoggerFactory() {
}
public Logger getLogger(String name) {
return NOPLogger.NOP_LOGGER;
}
}
最终我们看到 返回的 NOPLogger 也是继承 Logger。
至此,这也是一例 工厂方法模式。