设计模式——工厂模式

定义

        工厂模式是一种提供了最佳的创建对象的方式,将对象的实例化封装在了工厂类中,提供一种接口来创建不同的对象,使用者使用时,只需根据需求调用工厂类中不同的方法即可获取想创建的对象实例。

工厂方法

意图

        定义一个创建对象的接口,让其子类自己决定实例化哪个工厂类,工厂模式使其创建过程延迟到子类进行。

应用场景

        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工厂类去扩展抽象工厂类,然后创建一个工厂创造器/生成器类 FactoryProducerAbstractFactoryPatternDemo 类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递球类信息 BallFootBall/BasketBall/TanisBall),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递游戏信息 GameLOL/ 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();

总结

        工厂模式是最常用的设计模式之一,它包含三种实现,简单工厂、工厂方法、抽象工厂,每种实现都有优劣,该博客若对你有帮助,请关注我,后续更新更多内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值