前言
在之前提到的简单工厂模式中,如果需要创建新的产品类就必须修改工厂类的代码,这就违背了开闭原则。如果采用工厂方法模式的话,只需要再创建一个工厂类就可以了。
介绍
定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
角色
抽象工厂(Creator)角色:是工产方法模式的核心,与应用程序无关。任何在模式中创建的对象对的工厂类必须实现这个接口。
具体工厂(Concrete Creator)角色:这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建产品对象。
抽象产品(Product)角色:工厂方法模式创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口
具体产品(Concrete Product)角色:这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,他们之间往往一一对应。
类图
![这里写图片描述](https://img-blog.csdn.net/20180110172936116?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvU2VyZW5kaXBpdHlfeGw=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
代码实现
抽象工厂类(接口)
package 工厂方法模式;
/**
* @author 谢英亮
* @date 2018年1月5日 上午8:56:24
* @Description: 抽象的工厂接口
*/
public interface ICarFactory {
Car getCar();
}
具体工厂类
package 工厂方法模式;
/**
* @author 谢英亮
* @date 2018年1月5日 上午8:57:35
* @Description: 具体的工厂类
*/
public class BusFactory implements ICarFactory{
@Override
public Car getCar() {
return new Bus();
}
}
package 工厂方法模式;
/**
* @author 谢英亮
* @date 2018年1月5日 上午8:57:35
* @Description: 具体的工厂类
*/
public class BikeFactory implements ICarFactory{
@Override
public Car getCar() {
return new Bike();
}
}
抽象产品类(接口)
package 工厂方法模式;
/**
* @author 谢英亮
* @date 2018年1月5日 上午8:51:51
* @Description: 抽象产品类 :定义Car 交通工具类
*/
public interface Car {
void gotoWork();
}
具体产品类
package 工厂方法模式;
/**
* @author 谢英亮
* @date 2018年1月5日 上午8:54:38
* @Description: 实际的产品类
*/
public class Bike implements Car {
@Override
public void gotoWork() {
System.out.println("骑自行车去上班!");
}
}
package 工厂方法模式;
/**
* @author 谢英亮
* @date 2018年1月5日 上午8:54:38
* @Description: 实际的产品类
*/
public class Bus implements Car {
@Override
public void gotoWork() {
System.out.println("坐公交车去上班!");
}
}
总结
优点
1、一个调用者想创建一个对象,只要知道其名称就可以了,降低了耦合度。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。使得代码结构更加清晰。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点
每次增加一个产品时,都需要增加一个具体类和对象实现工厂(这里可以使用反射机制来避免),使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。所以对于简单对象来说,使用工厂模式反而增加了复杂度。