(一) 工厂模式概述
工厂模式: 是Java中最常用的设计模式之一, 它提供了一种创建对象的最佳方式. 在工厂模式中, 我们在使用工厂类创建对象时 不会对客户端暴露 创建逻辑, 并且是通过使用一个共同的接口来指向新创建的对象
(二) 简单工厂模式
简单工厂模式: 定义一个创建对象的工厂类, 由工厂类决定创建出哪一种对象的实例, 工厂类内部已封装创建出哪一种对象的实例的逻辑代码
Phone 手机接口
interface Phone {
// 运行手机的抽象方法
void run();
}
IPhone 苹果手机实现类
class IPhone implements Phone{
@Override
public void run() {
System.out.println("运行苹果手机");
}
}
HuaweiPhone 华为手机实现类
class HuaweiPhone implements Phone {
@Override
public void run() {
System.out.println("运行华为手机");
}
}
PhoneFactory 定义一个创建Phone对象实例的手机工厂类, 内部已封装创建出哪一种品牌手机实例的逻辑代码
class PhoneFactory {
public Phone createPhone(String phoneType) {
Phone phone = null;
if ("IPhone".equals(phoneType)) {
phone = new IPhone();
} else if ("HuaweiPhone".equals(phoneType)) {
phone = new HuaweiPhone();
}
return phone;
}
}
测试
public class SimpleFactory {
public static void main(String[] args) {
// 创建手机工厂类
PhoneFactory phoneFactory = new PhoneFactory();
// 通过手机工厂类创建 IPhone手机实例对象
Phone IPhone = phoneFactory.createPhone("IPhone");
IPhone.run(); // 运行苹果手机
// 通过手机工厂类创建 HuaweiPhone手机实例对象
Phone HuaweiPhone = phoneFactory.createPhone("HuaweiPhone");
HuaweiPhone.run(); // 运行华为手机
}
}
简单工厂模式: 是使用工厂类来创建不同实例的对象, 可以将创建对象的方法静态化, 代码更简洁明了
public class PhoneFactory {
public static Phone createPhone(String phoneType) {
Phone phone = null;
if ("IPhone".equals(phoneType)) {
phone = new IPhone();
} else if ("HuaweiPhone".equals(phoneType)) {
phone = new HuaweiPhone();
}
return phone;
}
}
// 可以直接通过 PhoneFactory.createPhone("phoneType") 创建手机对象
简单工厂模式存在问题
- 工厂类集中了所有实例(品牌手机)的创建逻辑,一旦这个工厂类不能正常工作,整个系统都会受到影响
- 违背了开闭原则(对扩展是开放的, 对修改时关闭的), 一旦添加新对象实例(新品牌手机)就不得不修改工厂类的逻辑
(三) 工厂方法模式
工厂方法模式: 先定义一个工厂父类 (负责定义创建对象的抽象接口). 再定义一个工厂子类 (负责生成具体的对象), 工厂方法模式将对象的实例化推迟到工厂子类
Phone 手机抽象类、IPhone 苹果手机实现类 和 HuaweiPhone 华为手机实现类
/**
* Phone 手机抽象类: 提供运行手机的抽象方法
*/
abstract class Phone {
abstract void run();
}
/**
* IPhone 运行苹果手机
*/
class IPhone extends Phone{
@Override
public void run() {
System.out.println("运行苹果手机");
}
}
/**
* HuaweiPhone 运行华为手机
*/
class HuaweiPhone extends Phone {
@Override
public void run() {
System.out.println("运行华为手机");
}
}
先定义一个工厂抽象父类: 提供创建手机对象的抽象方法
abstract class PhoneFactory {
abstract Phone createPhone();
}
再定义一个苹果工厂子类: 负责创建具体的对象(苹果手机对象)
再定义一个华为工厂子类: 负责创建具体的对象(华为手机对象)
class IPhoneFactory extends PhoneFactory {
@Override
public IPhone createPhone() {
return new IPhone();
}
}
class HuaweiPhoneFactory extends PhoneFactory {
@Override
public HuaweiPhone createPhone() {
return new HuaweiPhone();
}
}
测试:
public class FactoryMethod {
public static void main(String[] args) {
// 苹果子类工厂 创建 苹果手机对象
IPhoneFactory iPhoneFactory = new IPhoneFactory();
IPhone iPhone = iPhoneFactory.createPhone();
iPhone.run(); // 运行苹果手机
// 华为子类工厂 创建 华为手机对象
HuaweiPhoneFactory huaweiPhoneFactory = new HuaweiPhoneFactory();
HuaweiPhone huaweiPhone = huaweiPhoneFactory.createPhone();
huaweiPhone.run(); // 运行华为手机
}
}
工厂方法模式存在问题: 对象父类 与 对象工厂父类 一一对应, 对象子类 与 对象工厂子类 一一对应. 即: 一个具体工厂子类只能创建一类产品
(四) 抽象工厂模式
抽象工厂模式: Abstarct Factory Pattern, 是围绕一个超级工厂创建其他工厂, 该超级工厂又称为其他工厂的工厂.
在抽象工厂模式中, 超级工厂中提供多个接口, 每个接口负责创建一个相关对象的其他工厂, 工厂创建的对象 不需要显式指定它们的类, 指向抽象类
在抽象工厂模式中, 超级工厂子类负责创建具体的对象: 一个具体超级工厂子类创建多类产品
/**
* 电子产品超级工厂: 超级工厂创建其他工厂
* 创建手机工厂的抽象方法
* 创建电脑工厂的抽象方法
*/
abstract class ElectronicProductsFactory {
/**
* 手机工厂 创建Phone手机抽象对象
* @return
*/
abstract Phone createPhoneFactory();
/**
* 电脑工厂 创建Computer电脑抽象对象
* @return
*/
abstract Computer createComputerFactory();
}
在抽象工厂模式中, 超级工厂子类负责创建具体的对象: 一个具体超级工厂子类创建多类产品
/**
* 苹果超级工厂子类: 创建苹果手机和苹果电脑对象
*/
class AppleFactory extends ElectronicProductsFactory {
@Override
IPhone createPhoneFactory() {
return new IPhone();
}
@Override
AppleComputer createComputerFactory() {
return new AppleComputer();
}
}
/**
* 华为超级工厂子类: 创建华为手机和华为电脑对象
*/
class HuaweiFactory extends ElectronicProductsFactory {
@Override
HuaweiPhone createPhoneFactory() {
return new HuaweiPhone();
}
@Override
HuaweiComputer createComputerFactory() {
return new HuaweiComputer();
}
}
定义 产品抽象类 和 产品实体类
/**
* 电子产品抽象族类
*/
abstract class ElectronicProducts {
abstract void run();
}
/**
* 手机电子产品抽象类
*/
abstract class Phone extends ElectronicProducts {
@Override
abstract void run();
}
/**
* 电脑电子产品抽象类
*/
abstract class Computer extends ElectronicProducts {
@Override
abstract void run();
}
/**
* IPhone 苹果手机实体类
*/
class IPhone extends Phone{
@Override
public void run() {
System.out.println("运行苹果手机");
}
}
/**
* HuaweiPhone 华为手机实体类
*/
class HuaweiPhone extends Phone {
@Override
public void run() {
System.out.println("运行华为手机");
}
}
/**
* AppleComputer 苹果电脑实体类
*/
class AppleComputer extends Computer {
@Override
public void run() {
System.out.println("运行苹果电脑");
}
}
/**
* HuaweiComputer 华为电脑实体类
*/
class HuaweiComputer extends Computer {
@Override
public void run() {
System.out.println("运行华为电脑");
}
}
抽象工厂模式的优缺点:
- 将具体产品对象的实例化 推迟到 超级工厂子类实现
- 超级工厂子类可以创建多个具体产品对象
- 新增具体产品类时, 只需要增加 具体产品类 和 具体超级工厂子类. 对于新的具体产品类符合开-闭原则
- 抽象工厂模式 对于新增 抽象产品类, 是需要修改源代码. 因此 抽象工厂模式 对于新的抽象产品类不符合开-闭原则
(五) 总结
工厂模式的意义: 将实例化对象的代码提取处理, 放到一个类中统一管理和维护, 达到和主项目的依赖关系的解耦, 从而提提高项目的扩展和维护性.
工厂模式的依赖抽象原则:
- 创建对象实例时, 不要直接new对象, 而是把这个new类的动作放在一个工厂的方法中, 并返回. 甚至是, 变量不要直接持有具体类的引用
- 不要让类继承具体的类, 而是继承抽象类 或者是 接口
- 不要覆盖类中已经实现的方法