Java设计模式 - 初学笔记 -工厂模式

本文详细介绍了工厂模式的三种形式:简单工厂模式、工厂方法模式和抽象工厂模式。通过实例展示了如何使用这些模式创建具有多态性的对象,以及如何在不修改已有代码的情况下扩展产品类型。简单工厂模式适用于具有相同接口或基类的对象,而工厂方法模式则用于特定类型的对象创建。抽象工厂模式则解决了创建一系列相互依赖的对象的问题,适用于需要一组相关或相互依赖对象的场景。
摘要由CSDN通过智能技术生成

本文将从以下三个方面讲解工厂模式:

  • 简单工厂模式
  • 工厂模式
  • 抽象工厂模式

一、简单工厂模式

首先简单工厂就是定义一个工厂类,然后根据参数的不同去创建不同的实例,他们都拥有一个共同的父类。简单工厂是工厂模式最简单实用的模式。

 先简单举个例子解释一下什么是简单工厂。每天我们都要做饭,米饭的做法有很多种,有炒饭、泡饭等等。一般情况下,我们会用一个对象去表示炒饭或者泡饭。

/**
 * 米饭(炒饭)
 */
public class friedRice {
    public void print() {
        System.out.println("炒饭");
    }
}

/**
 * 米饭(泡饭)
 */
public class paofan {
    public void print() {
        System.out.println("泡饭");
    }
}

但是现在不想吃炒饭了,决定以后变成吃蛋炒饭,但是原先的炒饭我又不能去废除。那就需要将上述的炒饭修改为蛋炒饭,但是原先已经有调用过炒饭的地方,我们都需要进行修改变成蛋炒饭,将一定增加我们修改代码的隐患与工作量。

当进行了简单工厂的封装之后,就变成了下面这样。

/**
 * 米饭接口
 */
public interface IRice {
    void print();
}

/**
 * 米饭(炒饭)
 */
public class friedRice implements IRice {
    @Override
    public void print() {
        System.out.println("一份炒饭")
    }
}

/**
 * 米饭(泡饭)
 */
public class paofan implements IRice {
    @Override
    public void print() {
        System.out.println("一份泡饭");
    }
}

 

我们有了一个公共的父类米饭。 然后子类继承父类实现具体的种类。

然后创建一个米饭工厂。

/**
 * 创建米饭工厂
 */
public class RiceFactory {
    public static IRice create(String type) {
        switch (type) {
            case "炒饭":
                return new friedRice();
            case "泡饭":
                return new paofan();
            default:
                return new friedRice();
        }
    }
}

@Test
public void test() throws Exception {
    //我要吃炒饭
    IRice rice = RiceFactory.create("炒饭");
    //我要吃泡饭
    rice = RiceFactory.create("泡饭");
    //吃什么由配置决定
    rice = RiceFactory.create(xxxConfig.getRiceType());
}

这样我们只需要根据参数的不同去生产不同的饭,哪怕后续我要吃蛋炒饭,我只需要在工厂里将炒饭的地方 return new FriedRice(); 修改为 return new FriedRiceWithEggs();就行,不需要在调用的地方将实例修改为蛋炒饭。

当然不是所有的对象都要用简单工厂模式,需要有一定的要求性:最好具有多态性的对象,一般都会实现相同的接口,或者继承相同的基类。同时,创建工厂的参数不建议在代码种写死,可以从数据库中、枚举或者配置中读取字段获取参数。

二、工厂模式

在简单工厂中,可以创建在工厂里预设好的米饭。但是实际上一个工厂不能生产所有的东西,比如奥迪汽车厂只生产奥迪汽车,并不会去生产比亚迪汽车,因为这种情况,就要有专门的汽车厂去生产特定的汽车。工厂模式相当于更专业的简单工厂。同样举个例子解释:

我们先定义汽车基类和子类。

/**
 * 汽车基类
 */
public abstract class BaseCar {
    public abstract void Go();
}

/**
 * 红旗汽车
 */
public class HongQiCar extends BaseCar {
    @Override
    public void Go() {
        System.out.println("红旗汽车开始行驶了!");
    }
}

/**
 * 奥迪汽车
 */
public class AoDiCar extends BaseCar {
    @Override
    public void Go() {
        System.out.println("奥迪汽车开始行驶了!");
    }
}

然后需要一个汽车工厂和子类。

/**
 * 汽车工厂基类
 */
public abstract class BaseFactory {
    public abstract BaseCar CreateCar();
}

/**
 * 红旗汽车工厂
 */
public class HongQiCarFactory extends BaseFactory {
    @Override
    public BaseCar CreateCar() {
        return new HongQiCar();
    }
}

/**
 * 奥迪汽车工厂
 */
public class AoDiCarFactory extends BaseFactory {
    @Override
    public BaseCar CreateCar() {
        return new AoDiCar();
    }
}

然后我们再去生产汽车。

public void testCreateCar() {
    //创建红旗汽车工厂对象。    
    BaseFactory hongQiCarFactory = new HongQiCarFactory();
    //创建奥迪汽车工厂对象
    BaseFactory aoDiCarFactory = new AoDiCarFactory();
    //生产一辆红旗汽车
    BaseCar hongQi = hongQiCarFactory.CreateCar();
    hongQi.Go();
    //生产一辆奥迪汽车   
    BaseCar aoDi = aoDiCarFactory.CreateCar();
    aoDi.Go();
}

很容易理解,我们有一个公共的基类汽车厂,然后用汽车厂去定义专门品牌的汽车厂比如奥迪汽车厂、红旗汽车厂。当我们需要生产奥迪的时候,我们只需要创建一个奥迪的汽车厂去生产奥迪,需要红旗的时候,就用红旗汽车厂去生产红旗。对于用户来说,用户只能知道生产奥迪的奥迪汽车厂,以及生产红旗的红旗汽车厂,但是至于工厂是怎么创建的无需知道。哪怕后续用户需要增加一个生产奔驰的汽车厂,也只需要用汽车厂定义一个奔驰汽车厂,无需改动已有的汽车厂类。减少修改到其他代码的隐患,很好的符合了开闭原则。

三、抽象工厂模式

在系统中经常会遇到面临一系列相互依赖的对象需要创建,抽象工厂就是解决创建一系列相互依赖的对象。同样使用一个房屋风格创建的例子解释。

首先房屋由很多部分构成,比如屋顶,地板,窗户,房门等,我们需要这些的创建的基类(没有风格限制)。

/**
 * 屋顶基类
 **/
public abstract class BaseRoof {
    public abstract void Create();
}

/**
 * 地板基类
 **/
public abstract class BaseFloor {
    public abstract void Create();
}

/**
 * 窗户基类
 **/
public abstract class BaseWindow {
    public abstract void Create();
}

/**
 * 房门基类
 **/
public abstract class BaseDoor {
    public abstract void Create();
}

然后,我们定义出两种风格的房屋部分去实现基类。

/**
 * 地板(欧式)
 */
public class EuropeanFloor extends BaseFloor {
    @Override
    public void Create() {
        System.out.println("创建欧式的地板");
    }
}

/**
 * 屋顶(欧式)
 */
public class EuropeanRoof extends BaseRoof {
    @Override
    public void Create() {
        System.out.println("创建欧式的房顶");
    }
}

/**
 * 窗户(欧式)
 */
public class EuropeanWindow extends BaseWindow {
    @Override
    public void Create() {
        System.out.println("创建欧式的窗户");
    }
}

/**
 * 房门(欧式)
 */
public class EuropeanDoor extends BaseDoor {
    @Override
    public void Create() {
        System.out.println("创建欧式的房门");
    }
}

/**
 * 地板(中式)
 */
public class ChineseFloor extends BaseFloor {
    @Override
    public void Create() {
        System.out.println("创建中式的地板");
    }
}

/**
 * 屋顶(中式)
 */
public class ChineseRoof extends BaseRoof {
    @Override
    public void Create() {
        System.out.println("创建中式的房顶");
    }
}

/**
 * 窗户(中式)
 */
public class ChineseWindow extends BaseWindow {
    @Override
    public void Create() {
        System.out.println("创建中式的窗户");
    }
}

/**
 * 房门(中式)
 */
public class ChineseDoor extends BaseDoor {
    @Override
    public void Create() {
        System.out.println("创建中式的房门");
    }
}

这样就有了两种不同风格的装修。然后我们需要一个创建无风格房子的工厂基类。

/**
 * 抽象工厂基类
 */
public abstract class BaseFactory {
    /**
     * 创建房顶
     */
    public abstract BaseRoof CreateRoof();

    /**
     * 创建地板
     */
    public abstract BaseFloor CreateFloor();

    /**
     * 创建窗户
     */
    public abstract BaseWindow CreateWindow();

    /**
     * 创建房门
     */
    public abstract BaseDoor CreateDoor();
}

再创建两种不同风格的房屋子类继承实现基类。

/**
 * 创建对象工厂(欧式)
 */
public class EuropeanFactory extends BaseFactory {
    /**
     * 创建房顶(欧式)
     */
    @Override
    public BaseRoof CreateRoof() {
        return new EuropeanRoof();
    }

    /**
     * 创建地板(欧式)
     */
    @Override
    public BaseFloor CreateFloor() {
        return new EuropeanFloor();
    }

    /**
     * 创建窗户(欧式)
     */
    @Override
    public BaseWindow CreateWindow() {
        return new EuropeanWindow();
    }

    /**
     * 创建房门(欧式)
     */
    @Override
    public BaseDoor CreateDoor() {
        return new EuropeanDoor();
    }
}

/**
 * 创建对象工厂(中式)
 */
public class ChineseFactory extends BaseFactory {
    /**
     * 创建房顶(中式)
     */
    @Override
    public BaseRoof CreateRoof() {
        return new ChineseRoof();
    }

    /**
     * 创建地板(中式)
     */
    @Override
    public BaseFloor CreateFloor() {
        return new ChineseFloor();
    }

    /**
     * 创建窗户(中式)
     */
    @Override
    public BaseWindow CreateWindow() {
        return new ChineseWindow();
    }

    /**
     * 创建房门(中式)
     */
    @Override
    public BaseDoor CreateDoor() {
        return new ChineseDoor();
    }
}

工厂准备好了,我们如何去调用工厂生产出我们需要的风格类型呢,我们只需要根据需要去创建出指定风格的工厂,然后使用这个工厂里的方法就可以创建出这种风格的房子。

public void testCreateCar() {
    //创建房子工厂(欧式)    
    BaseFactory europeanFactory = new EuropeanFactory();
    europeanFactory.CreateRoof().Create();
    europeanFactory.CreateFloor().Create();
    europeanFactory.CreateWindow().Create();
    europeanFactory.CreateDoor().Create();
    // 创建房子工厂(中式)    
    BaseFactory chineseFactory = new ChineseFactory();
    chineseFactory.CreateRoof().Create();
    chineseFactory.CreateFloor().Create();
    chineseFactory.CreateWindow().Create();
    chineseFactory.CreateDoor().Create();
}

 后续我如果需要增加其他风格的房子,我也只需要增加一个房屋工厂去继承基类实现另一个风格。

最后,欢迎大家评论区批评指教~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值