工厂模式属于创建型设计模式, 用工厂方法代替 new 操作, 让子类去决定实例化哪个类, 工厂方法将一个类的实例化延迟到子类
推荐访问我的个人网站, 排版更好看呦: https://chenmingyu.top/design-factory-method/
什么是工厂模式
定义一个创建对象的接口, 由子类去决定实例化哪一个类, 将实例化对象的操作延迟到子类
优点:
解耦: 调用方不用负责对象的创建, 只需要使用, 明确各自的职责
维护方便: 后期如果创建对象时需要修改代码, 也只需要去工厂方法中修改, 易拓展
工厂模式细分为: 简单工厂, 工厂模式, 抽象工厂
简单工厂
以游戏为例子, 涉及四个类: GameFactory(游戏工厂类),Gameable(游戏接口),ShootGame(射击类游戏),TowerDefenceGame(塔防类游戏)
比如游戏工厂, 工厂方法通过出入的参数生成生成不同产品类型的游戏
Gameable
游戏接口, 提供一个校验账户信息的接口
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:19
- * @description:
- */
- public interface Gameable {
- /**
- * 校验账户信息
- * @param nickName
- */
- void validateAccount(String nickName);
- }
- ShootGame
射击类游戏, 实现 Gameable 接口
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:26
- * @description: 射击类游戏
- */
- public class ShootGame implements Gameable{
- @Override
- public void validateAccount(String nickName) {
- System.out.println("射击游戏校验昵称:"+nickName);
- }
- }
- TowerDefenceGame
塔防类游戏, 实现 Gameable 接口
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:28
- * @description: 塔防类游戏
- */
- public class TowerDefenceGame implements Gameable{
- @Override
- public void validateAccount(String nickName) {
- System.out.println("塔防游戏校验昵称:"+nickName);
- }
- }
- GameFactory
游戏工厂, 封装了创建游戏对象的过程
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:29
- * @description: 工厂类
- */
- public class GameFactory {
- /**
- * 根据传入类型生成实例
- * @param gameType
- * @return
- */
- public static Gameable creator(String gameType){
- Gameable gameable = null;
- if(StringUtils.isEmpty(gameType)){
- return gameable;
- }
- if("shoot".equalsIgnoreCase(gameType)){
- gameable = new ShootGame();
- }else if("towerDefence".equalsIgnoreCase(gameType)){
- gameable = new TowerDefenceGame();
- }
- return gameable;
- }
- }
测试
客户端决定实例化哪个对象
- public static void main(String[] args) {
- Gameable shootGame = GameFactory.creator("shoot");
- shootGame.validateAccount("明羽");
- System.out.println("... 分割线 ...");
- Gameable towerDefenceGame = GameFactory.creator("towerDefence");
- towerDefenceGame.validateAccount("明羽");
- }
输出
射击游戏校验昵称: 明羽
... 分割线 ...
塔防游戏校验昵称: 明羽
如果要新增一个拳击类游戏的话, 就需要新建一个拳击游戏类, 然后修改工厂方法.
工厂模式
工厂模式跟简单工厂模式的区别在于简单工厂只有一个工厂类, 提供了一个工厂方法, 由入参决定生产那个产品, 而工厂模式则定义一个工厂接口, 不同的产品工厂实现工厂接口, 生产的产品由产品工厂决定
以游戏为例子, 在上面四个类的基础上修改 GameFactory(游戏工厂类) 为接口, 新增了两个类: ShootGameFactory(射击类游戏工厂),TowerDefenceGameFactory(塔防类游戏工厂)
修改了的 GameFactory
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:29
- * @description: 工厂类
- */
- public interface GameFactory {
- /**
- * 生成实例
- * @return
- */
- Gameable creator();
- }
- ShootGameFactory
实现 GameFactory, 重写 creator()
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 15:14
- * @description: 射击类游戏工厂
- */
- public class ShootGameFactory implements GameFactory{
- @Override
- public Gameable creator() {
- return new ShootGame();
- }
- }
- TowerDefenceGameFactory
实现 GameFactory, 重写 creator()
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 15:15
- * @description: 塔防类游戏工厂
- */
- public class TowerDefenceGameFactory implements GameFactory{
- @Override
- public Gameable creator() {
- return new TowerDefenceGame();
- }
- }
测试
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:38
- * @description:
- */
- public class FactoryTest {
- public static void main(String[] args) {
- GameFactory shootGameFactory = new ShootGameFactory();
- Gameable shootGame = shootGameFactory.creator();
- shootGame.validateAccount("明羽");
- System.out.println("... 分割线 ...");
- GameFactory towerDefenceGameFactory = new TowerDefenceGameFactory();
- Gameable towerDefenceGame = towerDefenceGameFactory.creator();
- towerDefenceGame.validateAccount("明羽");
- }
- }
输出
射击游戏校验昵称: 明羽
... 分割线 ...
塔防游戏校验昵称: 明羽
抽象工厂
抽象工厂比工厂模式更为抽象, 工厂模式只生产一种产品族, 而抽象工厂生产多个产品族
产品族是指同一工厂生产的一组不同产品结构的一组产品, 比如射击游戏工厂生产单人射击游戏和双人射击游戏两款产品, 这里的单人射击游戏产和双人射击游戏两款产品统称为产品族
以上面的游戏为例, 现在有射击游戏和塔防游戏俩款游戏, 现在需求变了, 要求射击类游戏又细分为单人和双人两款游戏产品, 塔防类游戏细分为单人和双人两款游戏产品. 这时射击类游戏和塔防类游戏就是两个产品族, 旗下分别有两款产品一款是单人游戏, 一款是双人游戏
类图
有点复杂, 画个类图, 看着清晰一些
GameFactory: 抽象工厂, 规定了生成单人和双人两种游戏
ShootGameFactory,ShootGameFactory: 具体工厂, 负责生产具体的射击类和塔防类单, 双人游戏
Gameable 是抽象产品, ShootGame 和 TowerDefenceGame 是抽象类, 继承 Gameable
SingleShootGame,DoubleShootGame,SingleTowerDefenceGame,DoubleTowerDefenceGame 是具体产品
GameFactory
抽象工厂, 规定了生成单人和双人两种游戏
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:29
- * @description: 抽象工厂
- */
- public interface GameFactory {
- /**
- * 生产单人游戏
- * @return
- */
- Gameable createSingleGame();
- /**
- * 生产双人游戏
- * @return
- */
- Gameable createDoubleGame();
- }
- ShootGameFactory
具体工厂, 负责生产具体的射击类单人游戏和射击类双人游戏
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 18:20
- * @description: 设计游戏制造厂
- */
- public class ShootGameFactory implements GameFactory{
- @Override
- public Gameable createSingleGame() {
- return new SingleShootGame();
- }
- @Override
- public Gameable createDoubleGame() {
- return new DoubleShootGame();
- }
- }
- TowerDefenceGameFactory
具体工厂, 负责生产具体的塔防类单人游戏和塔防类双人游戏
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 18:20
- * @description: 塔防游戏制造厂
- */
- public class TowerDefenceGameFactory implements GameFactory {
- @Override
- public Gameable createSingleGame() {
- return new SingleTowerDefenceGame();
- }
- @Override
- public Gameable createDoubleGame() {
- return new DoubleTowerDefenceGame();
- }
- }
- Gameable
抽象产品, 所有游戏产品均实现该接口
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:19
- * @description: 游戏接口
- */
- public interface Gameable {
- /**
- * 校验账户信息
- * @param nickName
- */
- void validateAccount(String nickName);
- /**
- * 游戏人数
- */
- void getPlayerNumber();
- }
ShootGame 和 TowerDefenceGame
抽象类, 实现 Gameable 接口
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:26
- * @description: 射击类游戏
- */
- public abstract class ShootGame implements Gameable{
- @Override
- public void validateAccount(String nickName) {
- System.out.println("射击游戏校验昵称:"+nickName);
- }
- }
- /**
- * @auther: chenmingyu
- * @date: 2019/2/14 11:28
- * @description: 塔防类游戏
- */
- public abstract class TowerDefenceGame implements Gameable{
- @Override
- public void validateAccount(String nickName) {
- System.out.println("塔防游戏校验昵称:"+nickName);
- }
- }
具体产品
共四款游戏产品: SingleShootGame,DoubleShootGame,SingleTowerDefenceGame,DoubleTowerDefenceGame
- /**
- * @auther: chenmingyu
- * @date: 2019/2/15 16:55
- * @description: 单人射击游戏
- */
- public class SingleShootGame extends ShootGame {
- @Override
- public void getPlayerNumber() {
- System.out.println("这是一个单人玩的射击游戏");
- }
- }
- /**
- * @auther: chenmingyu
- * @date: 2019/2/15 16:57
- * @description: 双人射击游戏
- */
- public class DoubleShootGame extends ShootGame{
- @Override
- public void getPlayerNumber() {
- System.out.println("这是一个双人玩的射击游戏");
- }
- }
- /**
- * @auther: chenmingyu
- * @date: 2019/2/15 17:17
- * @description: 单人塔防游戏
- */
- public class SingleTowerDefenceGame extends TowerDefenceGame{
- @Override
- public void getPlayerNumber() {
- System.out.println("这是一个单人玩的塔防游戏");
- }
- }
- /**
- * @auther: chenmingyu
- * @date: 2019/2/15 17:18
- * @description: 双人塔防游戏
- */
- public class DoubleTowerDefenceGame extends TowerDefenceGame{
- @Override
- public void getPlayerNumber() {
- System.out.println("这是一个双人玩的塔防游戏");
- }
- }
测试
- public static void main(String[] args) throws Exception{
- ShootGameFactory shootGameFactory = new ShootGameFactory();
- shootGameFactory.createSingleGame().getPlayerNumber();
- shootGameFactory.createDoubleGame().getPlayerNumber();
- TowerDefenceGameFactory towerDefenceGameFactory = new TowerDefenceGameFactory();
- towerDefenceGameFactory.createSingleGame().getPlayerNumber();
- towerDefenceGameFactory.createDoubleGame().getPlayerNumber();
- }
输出
这是一个单人玩的射击游戏
这是一个双人玩的射击游戏
这是一个单人玩的塔防游戏
这是一个双人玩的塔防游戏
来源: https://www.cnblogs.com/cmyxn/p/10387529.html