【设计模式-2.2】创建型——简单工厂和工厂模式

说明:本文介绍设计模式中,创建型设计模式中的工厂模式;

飞机大战

创建型设计模式,关注于对象的创建,本文介绍的简单工厂和工厂模式同样也是。举一个游戏例子,如飞机大战游戏中,屏幕中敌人类型有坦克、飞机,会随机出现在画面的上方;

在这里插入图片描述
我们可以简单的将敌人抽象为一个抽象类,然后分别创建对应的实现类,如下:

(敌人抽象类,注意属性的修饰符,protected,子类中需要用到)

/**
 * 敌人抽象类
 */
public abstract class Enemy {
    
    

    /**
     * 敌人的坐标
     */
    protected int x;

    /**
     * 敌人的坐标
     */
    protected int y;

    /**
     * 抽象方法
     */
    public Enemy(int x, int y) {
    
    
        this.x = x;
        this.y = y;
    }

    /**
     * 绘制方法
     */
    public abstract void show();
}

(具体实现类,坦克)

/**
 * 坦克
 */
public class Tank extends Enemy{
    
    

    public Tank(int x, int y) {
    
    
        super(x, y);
    }

    @Override
    public void show() {
    
    
        System.out.println("坦克出现了,坐标是:" + x + "," + y);
    }
}

(具体实现类,飞机)

/**
 * 飞机
 */
public class AirPlane extends Enemy{
    
    

    public AirPlane(int x, int y) {
    
    
        super(x, y);
    }

    @Override
    public void show() {
    
    
        System.out.println("飞机出现了,坐标是:" + x + "," + y);
    }
}

(客户端,client)

import java.util.Random;

/**
 * 客户端
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 屏幕宽度是100
        int screenLength = 100;

        // 创建坦克
        Enemy tank = new Tank(new Random().nextInt(screenLength),0);
        tank.show();

        // 创建飞机
        Enemy airPlane = new AirPlane(new Random().nextInt(screenLength),0);
        airPlane.show();
    }
}

执行结果:

在这里插入图片描述

分析:以上创建方式,有两点不足之处,对象的创建和使用在一起,耦合性太高;创建对象的代码放到了客户端类里,如果需要创建多个对象的话,客户端的代码势必会越来越臃肿

简单工厂

为了解决上面提到的两个问题,耦合性高,客户端代码臃肿,我们可以使用简单工厂对上面的流程进行改进。如下,创建一个简单工厂类,将创建对象的步骤抽取到这里面:

import java.util.Random;

/**
 * 简单工厂
 */
public class SimpleFactory {
    
    

    /**
     * 屏幕宽度
     */
    private int screenLength;

    /**
     * 随机数
     */
    private Random random;

    /**
     * 构造函数
     *
     * @param screenLength
     */
    public SimpleFactory(int screenLength) {
    
    
        this.screenLength = screenLength;
        this.random = new Random();
    }

    /**
     * 创建敌人
     * @param type
     * @return
     */
    public Enemy createEnemy(String type) {
    
    
        int x = random.nextInt(screenLength);
        Enemy enemy = null;
        switch (type) {
    
    
            case "Tank":
                enemy = new Tank(x, 0);
                break;
            case "AirPlane":
                enemy = new AirPlane(x, 0);
                break;
            default:
                throw new RuntimeException("unknown enemy type");
        }
        return enemy;
    }
}

这样,客户端就可以使用这个简单工厂来创建对象了,如下:

/**
 * 客户端
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        int screenLength = 100;
        new SimpleFactory(screenLength).createEnemy("Tank").show();
        new SimpleFactory(screenLength).createEnemy("AirPlane").show();
    }
}

执行结果:

在这里插入图片描述
分析:通过简单工厂,对对象的创建进行了封装,使客户端的代码简单、清爽。但是,如果需要增加敌人类型的话,我们就需要去修改这个简单工厂类,新增case分支,这不利于后续的代码扩展

工厂模式

使用工厂模式,可以弥补简单工厂的缺点。我们可以创建一个工厂接口,让后续所有的敌人对象都实现这个接口,并实现其抽象方法,把对象的创建放到具体实现类中,这样后续无论新增多少种敌人类型,都只要实现这个接口即可,不需要对原有系统进行修改。如下:

(工厂接口)

/**
 * 敌人工厂接口
 */
public interface Factory {
    
    

    /**
     * 创建敌人
     * 
     * @param screenLength
     * @return
     */
    Enemy createEnemy(int screenLength);
}

(飞机工厂)

import java.util.Random;

/**
 * 飞机工厂
 */
public class AirPlaneFactory implements Factory{
    
    

    @Override
    public Enemy createEnemy(int screenLength) {
    
    
        return new AirPlane(new Random().nextInt(screenLength), 0);
    }
}

(坦克工厂)

import java.util.Random;

/**
 * 坦克工厂
 */
public class TankFactory implements Factory{
    
    

    @Override
    public Enemy createEnemy(int screenLength) {
    
    
        return new Tank(new Random().nextInt(screenLength), 0);
    }
}

现在,如果需要新增一个Boss对象,只需要创建对应的Boss对象,及其工厂实现类即可,如下:

(Boss类)

/**
 * Boss
 */
public class Boss extends Enemy{
    
    

    public Boss(int x, int y) {
    
    
        super(x, y);
    }

    @Override
    public void show() {
    
    
        System.out.println("Boss出现了,坐标是:" + x + "," + y);
    }
}

(Boss工厂实现类,用于创建Boss)

import java.util.Random;

/**
 * Boss工厂
 */
public class BossFactory implements Factory {
    
    

    @Override
    public Enemy createEnemy(int screenLength) {
    
    
        // Boss出现在屏幕正中间
        return new Boss(screenLength / 2, 0);
    }
}

(客户端代码,客户端只需创建工厂对象,调用其方法即可)

/**
 * 客户端
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        // 屏幕宽度
        int screenLength = 100;

        // 创建坦克
        Factory tankFactory = new TankFactory();
        for (int i = 0; i < 10; i++) {
    
    
            tankFactory.createEnemy(screenLength).show();
        }

        // 创建飞机
        Factory airFactory = new AirPlaneFactory();
        for (int i = 0; i < 10; i++) {
    
    
            airFactory.createEnemy(screenLength).show();
        }

        // 创建Boss
        Factory boosFactory = new BossFactory();
        boosFactory.createEnemy(screenLength).show();
    }
}

执行结果:

在这里插入图片描述

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

猜你喜欢

转载自blog.csdn.net/qq_42108331/article/details/134668774