综述:简单的说工厂模式就是提供一个工厂方法,传入指定的参数得到我想要的对象。
为什么要使用工厂模式?
1、考虑这样一个问题,对于一个类A,当A被使用的地方很多,则很多地方都会使用new来创建对象,肯定会导致使用A的地方有很多代码重复。
2、考虑当A有功能改变时,使用A的地方的所有代码都需要改变,很是麻烦。
3、如果一个抽象类有很多子类,当需要更改需求,调用其他子类时,则需要修改业务逻辑的类,这样不符合一般的设计原则。
基于以上的问题,工厂模式应运而生。使用工厂模式吧创建对象的操作放在其中,需要使用指定类对象的地方就从工厂中获取,这样既避免了重复代码,在修改功能时,也只需要修改工厂类就可以了,也就是说通过工厂模式创建,则将创建和引用解耦,只需要修改创建部分就可以了。
工厂模式的分类
工厂模式的分类有三种:
(1)简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method Pattern)
(2)工厂方法(Factory Method)模式
(3)抽象工厂(Abstract Factory)模式
在学习工厂模式之前必读文章,工厂模式的作用:创建对象与使用对象——谈谈工厂的作用
一、简单工厂模式
有一个工厂可以生产产品,A、B两种产品都有produce的功能
1、创建接口
public interface Product{
public void produce();
}
2、接口的实现类
class A implements Product{
@Override
public void produce() {
System.out.println("produce -- A");
}
}
class B implements Product{
@Override
public void produce() {
System.out.println("produce -- B");
}
}
3、工厂类
public class SimpleFactory {
public static Product produce(String name){
if("A".equals(name))
return new A();
else if("B".equals(name))
return new B();
else
return null;
}
}
4、测试类
public class Main {
public static void main(String[] args) {
Product product = SimpleFactory.produce("A");
product.produce();
Product product1 = SimpleFactory.produce("B");
product1.produce();
/**
* produce -- A
* produce -- B
*/
}
}
从上面可以看到,当我们需要改变功能的时候,就需要改变上面的工厂,这很明显不符合 开放-封闭原则 。
通过反射来改进上面的工厂类
public class SimpleFactory {
public static Object produce(Class<? extends Product> name){ //继承Product的Class对象
Object o = null;
try {
o = Class.forName(name.getName()).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return o;
}
}
测试类
public class Main {
public static void main(String[] args) {
Product product = (Product) SimpleFactory.produce(com.demo.factory.A.class);
product.produce();
Product product1 = (Product) SimpleFactory.produce(com.demo.factory.B.class);
product1.produce();
/**
* produce -- A
* produce -- B
*/
}
}
经过改进之后,工厂类满足了开闭原则,对于这种方式,可以考虑利用 反射 + 配置文件的方式,以减少在使用工厂处使用全类名。
二、工厂方法模式
工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压力可以由工厂方法模式里不同的工厂子类来分担。
那么对于刚才的静态工厂模式我们可以这样改进,首先创建一个工厂接口,如下
public interface FactoryInterface {
public Product produces();
}
然后分别创建A类的工厂类和B类的工厂类并都实现FactoryInterface接口,如下
public class A_Factory implements FactoryInterface {
@Override
public Product produces() {
return new A();
}
}
public class B_Factory implements FactoryInterface {
@Override
public Product produces() {
return new B();
}
}
测试类
public class Main {
public static void main(String[] args) {
A a = (A) new A_Factory().produces();
a.produce();
B b = (B) new B_Factory().produces();
b.produce();
/**
* produce -- A
* produce -- B
*/
}
}
三、抽象工厂模式
看了很多博客,说抽象工厂模式都很抽象,但是结合实例来分析就相对来说比较容易理解了。抽象工厂是生产一整套有产品的(至少要生产两个产品),这些产品必须相互是有关系或有依赖的;而工厂方法中的工厂是生产单一产品的工厂。以鞋子和鞋带为例进一步理解抽象工厂模式:
鞋子接口
public interface Shoes {
public void exercise();
}
鞋带接口
public interface Shoelaces {
public void tie();
}
Anta类
public class Anta implements Shoes{
@Override
public void exercise() {
System.out.println("安踏鞋子");
}
}
耐克类
public class Nike implements Shoes{
@Override
public void exercise() {
System.out.println("耐克鞋子");
}
}
安踏鞋带类
public class AntaShowlaces implements Shoelaces {
@Override
public void tie() {
System.out.println("安踏鞋子系鞋带");
}
}
耐克鞋带类
public class NikeShowlaces implements Shoelaces {
@Override
public void tie() {
System.out.println("耐克鞋子系鞋带");
}
}
工厂接口
public interface Factory { //工厂
public Shoes produceShoes();
public Shoelaces produceShoelaces();
}
安踏工厂
public class AntaFactory implements Factory{
@Override
public Shoes produceShoes() {
return new Anta();
}
@Override
public Shoelaces produceShoelaces() {
return new AntaShowlaces();
}
}
耐克工厂
public class NikeFactory implements Factory{
@Override
public Shoes produceShoes() {
return new Nike();
}
@Override
public Shoelaces produceShoelaces() {
return new NikeShowlaces();
}
}
测试
public class Test {
public static void main(String[] args) {
Anta anta = (Anta) new AntaFactory().produceShoes();
anta.exercise();
AntaShowlaces antaShowlaces = (AntaShowlaces) new AntaFactory().produceShoelaces();
antaShowlaces.tie();
Nike nike = (Nike) new NikeFactory().produceShoes();
nike.exercise();
NikeShowlaces nikeShowlaces = (NikeShowlaces) new NikeFactory().produceShoelaces();
nikeShowlaces.tie();
/**
* 安踏鞋子
* 安踏鞋子系鞋带
* 耐克鞋子
* 耐克鞋子系鞋带
*
*/
}
}
和工厂方法模式区别
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个(产品族)。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例(一对一),而抽象工厂模式可以创建多个具体产品类的实例(一对多)。