工厂模式也是一种生产对象的设计模式,其应用场景的一个重要特点就是:多态。如果说一些类采用工厂的设计模式,那么在设计类的过程中,一般先会有一个基本的接口,然后再其他类来实现接口,从而形成一个类似于父子的关系。
工厂模式的分类有:
一。简单工厂模式:代码简单,结构清晰,通过一个第三方的工厂类来实现调用者和实体类的解耦。代码如下:
1.一个基本的接口:
public interface Car {
void run();
}
2.实现接口的类(Audi 和 Byd)
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪在跑");
}
}
public class Byd implements Car {
@Override
public void run() {
System.out.println("比亚迪在跑");
}
}
3.一个给客户端提供实体对象的工厂类
public class CarFactory {
public static Audi getAudi(){
return new Audi();
}
public static Byd getByd(){
return new Byd();
}
}
这样的话,外界通过工厂类的两个方法 getAudi()和getByd()来获得相应的对象,当然在设计类的过程中,我们也可以同时使用单例模式,这些外界都不关心,外界只要能获得对象实例就可以了,这样,我们的内部代码就可以相对隐藏起来。
其优点:实现解耦,便于扩展,符合面向对象的设计思想;
其缺点:扩展不是很方便,会修改原来的代码,可能造成对原来代码的破坏(对于这个,可不可以通过继承工厂类来解决呢?代码思路如下);
假设,我们要添加一个新的类(falali)
public class Falali implements Car {
@Override
public void run() {
System.out.println("falali在跑");
}
}
这个时候我们肯定不能在原来的CarFactory类中修改代码,那么我们可以通过创建一个类来继承CarFactory
public class MyCarFactory extends CarFactory {
public static Falali getFalali(){
return new Falali();
}
}
这个外界就可以通过MyCarFactory类的getFalali()方法来创建对象,并且也不会破坏原来的代码。
在工作中,一般是使用简单工厂模式就可以了,下面两种了解就可以了。
二。工厂方法模式:简单工厂模式的升级,不再是所有的实体类通过一个工厂类来提供所有对象的方法,而是每一个实体类都拥有自己对应的工厂类。代码如下:
1.一个实体类的接口和工厂类的接口
public interface Car { //用来约束实体类的行为
void run();
}
public interface CarFactory { //用来约束工厂类的行为
Car getInstance();
}
2.实现接口的实体类和相对应的工厂类
Audi类和对应的工厂类
public class Audi implements Car {
@Override
public void run() {
System.out.println("奥迪在跑");
}
}
public class AudiFactory implements CarFactory {
@Override
public Car getInstance() {
// TODO 自动生成的方法存根
return new Audi();
}
}
Byd类和对应的工厂类
public class Byd implements Car {
@Override
public void run() {
System.out.println("比亚迪在跑");
}
}
public class BydFactory implements CarFactory {
@Override
public Car getInstance() {
return new Byd();
}
}
这样的话,如果添加新的类falali,就可以直接写两个分别实现相应接口的类即可:
public class Falali implements Car {
@Override
public void run() {
System.out.println("falali在跑");
}
}
public class FalaliFactory implements CarFactory {
@Override
public Car getInstance() {
// TODO 自动生成的方法存根
return new Falali();
}
}
这样的话,类的扩张就会很简单,也不会涉及原来的代码,符合面向对象的ocp对象,缺点在于:代码复杂,结构复杂,在工作用一般不是使用这种,使用简单工厂模式就可以了。
三。抽象工厂模式:这个模式跟前两个不一样,抽象工厂模式一般用于多个不同类的组合。
比如一台电脑由主机和外设组成,而主机和外设都有两种规格(高档和入门),那么一台电脑的组装有四种情况:高档主机和高档外设,高档主机和入门外设,入门主机和高档外设,入门主机和入门外设。
1.三个接口:主机接口,外设接口,主机和外设组合的接口
public interface CHost {
void run();
}
public interface Multimedia {
void say();
}
public interface ComputerFactory {
CHost getChostInstance();
Multimedia getMultimediaInstance();
}
2.分别实现相应接口的实体类和一个生产高档主机和高档外设的工厂类
主机类:
public class ExpensiveCHost implements CHost{
@Override
public void run() {
System.out.println("我是高档主机");
}
}
public class LowCHost implements CHost{
@Override
public void run() {
System.out.println("我是入门主机");
}
}
外设类:
public class ExpensiveMultimedia implements Multimedia{
@Override
public void say() {
System.out.println("我是高档外设");
}
}
public class LowMultimedia implements Multimedia{
@Override
public void say() {
System.out.println("我是低档外设");
}
}
高档主机和高档外设组合电脑的工厂类:
public class ExpensiveComputer implements ComputerFactory {
public CHost getChostInstance() {
return new ExpensiveCHost();
}
public Multimedia getMultimediaInstance() {
return new ExpensiveMultimedia();
}
}
假设现在我们想生产一个低档外设和低档主机的电脑组合,那么我们直接新建一个工厂类就可以了。
public class LowComputer implements ComputerFactory {
public CHost getChostInstance() {
return new LowCHost();
}
public Multimedia getMultimediaInstance() {
return new LowMultimedia();
}
}
抽象工厂模式的优势在于:类与类直接的一个组合,不是针对于某一个单体的类的扩展,针对的是多个类直接的组合。
工厂模式的应用场景:JDK中Calender的getInastance();JDBC中connection的获取;Hibernate中SessionFactory获取session(工厂加单例);反射中的newInstance();servlet编程中的servlet(工厂加单例);
小结:工厂模式的核心在于解耦,在于类的扩展和升级。简单工厂模式代码简单,就是一个第三方的工厂类提供同一个接口的子类的实体对象的接口。工厂方法模式就是在简单工厂模式上进一步抽象,创建一个工厂接口,由每个实体类创建一个对应的工厂类,一对一服务。抽象工厂模式就是不同类直接的组合,关系更加复杂,但是一般工作中使用简单工厂模式即可,而且,设计模式也存在组合。