定义
工厂模式是一种提供了最佳的创建对象的方式,将对象的实例化封装在了工厂类中,提供一种接口来创建不同的对象,使用者使用时,只需根据需求调用工厂类中不同的方法即可获取想创建的对象实例。
工厂方法
意图
定义一个创建对象的接口,让其子类自己决定实例化哪个工厂类,工厂模式使其创建过程延迟到子类进行。
应用场景
1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。 2、Hibernate 换数据库只需换方言和驱动就可以。3、mybatis与数据库建立连接,只需换mybatis的配置即可。4、日志服务中日志可能记录到不同的业务中,记录到不同的位置中,通过工厂类来快速选择记录到哪里。
优点
1、创建对象的细节封装在工厂类内部,封装性好,使用者无需关心内部细节。
2、扩展性高,使用者可根据需求传入不同的参数,即可获取自己想要的对象实例。
缺点
1、每增加一个产品,除了增加具体类之外,还需增加一个对象实现工厂类,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
注意
对于简单的类,new出来的,无需使用工厂模式,因为工厂模式多了一个工厂类,会占用更多资源;对于复杂的类,可以考虑使用工厂模式。
工厂模式包含以下几个核心角色
- 抽象产品(Abstract Product):定义了产品的共同接口或抽象类。它可以是具体产品类的父类或接口,规定了产品对象的共同方法。
- 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。
- 抽象工厂(Abstract Factory):声明了创建产品的抽象方法,可以是接口或抽象类。它可以有多个方法用于创建不同类型的产品。
- 具体工厂(Concrete Factory):实现了抽象工厂接口,负责实际创建具体产品的对象。
实现
在这里,我们举一个例子来实现说明工厂模式。
创建一个接口
public interface Demo{
void play();
}
创建接口实现的实现类
public class BasketBall implements Demo{
@Override
public void play() {
System.out.println("play the basketball");
}
}
public class FootBall implements Demo{
@Override
public void play() {
System.out.println("play the football");
}
}
public class TanisBall implements Demo{
@Override
public void play() {
System.out.println("play the tanisball");
}
}
创建工厂
public class DemoFacotry{
//使用 getPlay 方法获取球类型的对象
public Demo getPlay(String ballType){
if(ballType== null){
return null;
}
if(ballType.equalsIgnoreCase("Basket")){
return new BasketBall();
} else if(ballType.equalsIgnoreCase("Foot")){
return new FootBall();
} else if(ballType.equalsIgnoreCase("Tanis")){
return new TanisBall();
}
return null;
}
}
之后,通过创建工厂实例去使用该工厂创建对应的对象实例。
DemoFactory factory = new DemoFactory();
Demo ball = factory.getPlay("BasketBall");
ball.play();
上述工厂模式属于工厂方法, 就是定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。除了工厂方法,还有简单工厂模式和抽象工厂模式。
简单工厂模式
简单工厂不算是一个真正的设计模式,而更像是一种我们的编程习惯,但是在平时编码中这不失为一个简单的方法,可以将客户程序从具体类解耦。
介绍
工厂类拥有一个工厂方法(create),接受了一个参数,通过不同的参数实例化不同的产品类。
抽象工厂模式
定义
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
例如,汽车可以分为轿车、SUV、MPV等,也分为奔驰、宝马等。我们可以将奔驰的所有车看作是一个产品族,而将宝马的所有车看作是另一个产品族。分别对应两个工厂,一个是奔驰的工厂,另一个是宝马的工厂。与工厂方法不同,奔驰的工厂不只是生产具体的某一个产品,而是一族产品(奔驰轿车、奔驰SUV、奔驰MPV)。“抽象工厂”的“抽象”指的是就是这个意思。 即相比于工厂方法,抽象工厂定义了一系列的产品,而不是一个产品。
上边的工厂方法模式是一种极端情况的抽象工厂模式(即只生产一种产品的抽象工厂模式),而抽象工厂模式可以看成是工厂方法模式的一种推广。
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
实现
下面举一个例子来说明这个实现
定义一个抽象工厂,AbstractFactory,然后定义GameFactory和BallFactory工厂类去扩展抽象工厂类,然后创建一个工厂创造器/生成器类 FactoryProducer。AbstractFactoryPatternDemo 类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递球类信息 Ball(FootBall/BasketBall/TanisBall),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递游戏信息 Game(LOL/ CS / CF),以便获取它所需对象的类型。
创建一个球类接口
public interface Ball{
void play();
}
创建接口实现的实现类
public class BasketBall implements Ball{
@Override
public void play() {
System.out.println("play the basketball");
}
}
public class FootBall implements Ball{
@Override
public void play() {
System.out.println("play the football");
}
}
public class TanisBall implements Ball{
@Override
public void play() {
System.out.println("play the tanisball");
}
}
创建游戏接口
public interface Game{
void play();
}
创建接口实现的实现类
public class LOL implements Game{
@Override
public void play() {
System.out.println("play the LOL");
}
}
public class CF implements Game{
@Override
public void play() {
System.out.println("play the CF");
}
}
public class CS implements Game{
@Override
public void play() {
System.out.println("play the CS");
}
}
为 Game和 Ball 对象创建抽象类来获取工厂。
public abstract class AbstractFactory {
public abstract Game getGame(String game);
public abstract Ball getBall(String ball);
}
创建扩展了 AbstractFactory 的工厂类,基于给定的信息生成实体类的对象
public class GameFactory extends AbstractFactory {
@Override
public Game getGame(String gameType){
if(gameType== null){
return null;
}
if(gameType.equalsIgnoreCase("LOL")){
return new LOL();
} else if(gameType.equalsIgnoreCase("CF")){
return new CF();
} else if(gameType.equalsIgnoreCase("CS")){
return new CS();
}
return null;
}
@Override
public Ball getBall(String ball) {
return null;
}
}
public class BallFactory extends AbstractFactory {
@Override
public Game getGame(String game){
return null;
}
@Override
public Ball getBall(String ballType) {
if(ballType== null){
return null;
}
if(ballType.equalsIgnoreCase("BasketBall")){
return new BasketBall();
} else if(ballType.equalsIgnoreCase("FootBall")){
return new FootBall();
} else if(ballType.equalsIgnoreCase("TanisBall")){
return new TanisBall();
}
return null;
}
}
创建一个工厂创造器/生成器类,通过传递球类或游戏信息来获取工厂
public class FactoryProducer {
public static AbstractFactory getFactory(String choice){
if(choice.equalsIgnoreCase("Ball")){
return new BallFactory();
} else if(choice.equalsIgnoreCase("Game")){
return new GameFactory();
}
return null;
}
}
之后就可以通过FactoryProducer获取AbstractFactory对象,再获取工厂中具体的事物即可
AbstractFactory gameFactory = FactoryProducer.getFactory("Game");
Game game = gameFactory.getGame("LOL");
game.play();
总结
工厂模式是最常用的设计模式之一,它包含三种实现,简单工厂、工厂方法、抽象工厂,每种实现都有优劣,该博客若对你有帮助,请关注我,后续更新更多内容。