核心思想
创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
类图
简单工厂把实例化的操作单独放到一个类中,这个类就成为简单工厂类,简单工厂处理创建对象的细节。
这样做能把客户类和具体子类的实现解耦,客户类不再需要知道有哪些子类以及应当实例化哪个子类。客户类往往有多个,如果不使用简单工厂,那么所有的客户类都要知道所有子类的细节。而且一旦子类发生改变,例如增加子类,那么所有的客户类都要进行修改。
实现
举个简单的例子,比如我们要根据不同的用户需求生产不同的服装类型。
我们先定义一个服装接口
package DesignPattern.Factory;
/**
* 服装类接口
* @author xudaxia0610
*/
public interface Clothes {
}
package DesignPattern.Factory;
/**
* T恤衫
* @author xudaxia0610
*/
public class TShirt implements Clothes{
}
package DesignPattern.Factory;
/**
* 大衣
* @author xudaxia0610
*/
public class Coat implements Clothes{
}
package DesignPattern.Factory;
/**
* 裤子
* @author xudaxia0610
*/
public class Trousers implements Clothes{
}
下面在客户类根据不同的需求生产不同的服装产品
package DesignPattern.Factory;
/**
* 客户类
* @author xudaxia0610
*/
public class Client {
public static void main(String[] args) {
int type = 1;
Clothes clothes = null;
if (type == 1) {
clothes = new TShirt();
} else if (type == 2) {
clothes = new Coat();
} else {
clothes = new Trousers();
}
// do something with the clothes
}
}
这种实现方式,虽然说没有问题,但是在以后服装产品有改动的时候,可能会给我们带来很多麻烦。
我们来将这个问题泛化一下,在 A 类里面只要 new 了一个 B 类的对象,那么 A 类就会从某种程度上依赖 B 类。如果在后期需求发生变化或者是维护的时候,需要修改 B 类的时候,我们就需要打开源代码修改所有与这个类有关的类了,这将是一件非常令人头痛的事情。
接下来,我们来看看使用简单工厂的实现如何解决这个麻烦。
package DesignPattern.Factory;
/**
* 简单工厂
* @author xudaxia0610
*/
public class SimpleClothesFactory {
public Clothes createClothes(int type) {
if (type == 1) {
return new TShirt();
} else if (type == 2) {
return new Coat();
}
return new Trousers();
}
}
客户类修改如下:
package DesignPattern.Factory;
/**
* 使用简单工厂的客户类
* @author xudaxia0610
*/
public class Client {
public static void main(String[] args) {
SimpleClothesFactory factory = new SimpleClothesFactory();
Clothes clothes = factory.createClothes(1);
// do something with the clothes
}
}
如上所示,使用简单工厂,我们就将客户类和具体子类的实现进行了解耦。