工厂设计模式是一种创建型设计模式,它提供了一种封装对象创建过程的方式,使得对象的创建与使用分离,从而提高了系统的可扩展性和可维护性。工厂模式主要分为三种:简单工厂模式、工厂方法模式和抽象工厂模式。本文将详细介绍这三种模式的定义、实现、优缺点及应用场景,并结合实际案例进行说明。
简单工厂模式通过一个专门的工厂类,根据传入的参数或条件来决定创建并返回哪一个具体的产品对象。它提供了一种创建对象的最佳方式,客户端无需关心对象的创建细节。
以汽车生产为例,定义一个接口Moveable
,表示可移动的物体,具体实现类为不同品牌的汽车。工厂类SimpleFactory
根据传入的参数决定创建哪种品牌的汽车。
// 接口
public interface Moveable {
void runRoad();
}
// 具体实现类
public class BydCar implements Moveable {
@Override
public void runRoad() {
System.out.println("[比亚迪]:一路同驰骋");
}
}
public class FerrariCar implements Moveable {
@Override
public void runRoad() {
System.out.println("[法拉利]:对车手来说,是速度...");
}
}
// 工厂类
public class SimpleFactory {
public Moveable getVehicle(String vehicleName) {
if (vehicleName.equalsIgnoreCase("BYD")) {
return new BydCar();
} else if (vehicleName.equalsIgnoreCase("FERRARI")) {
return new FerrariCar();
}
return null;
}
}
优点:简单直接,通过一个含参的工厂方法可以实例化任何产品类。
缺点:工厂类职责过重,增加新产品时需要修改工厂类逻辑,违背开闭原则。
适用于产品种类较少且不经常变动的场景。
工厂方法模式进一步解耦合,把工厂类进行抽象,不再负责所有实例的创建,而是把具体的创建工作交给其子类去完成。它定义了一个创建对象的接口,但由子类决定实例化哪一个类。
以电脑配件工厂为例,定义一个接口CpParts
,表示电脑配件,具体实现类为不同品牌的鼠标。抽象工厂类CpPartsFactory
定义了创建鼠标的方法,具体工厂类实现该方法。
// 接口
public interface CpParts {
void printName();
}
// 具体实现类
public class HpMouse implements CpParts {
@Override
public void printName() {
System.out.println("惠普鼠标 created!");
}
}
// 抽象工厂类
public abstract class CpPartsFactory {
public abstract CpParts create();
}
// 具体工厂类
public class HpMouseFactory extends CpPartsFactory {
@Override
public CpParts create() {
return new HpMouse();
}
}
优点:减轻了工厂类的负担,符合开闭原则,增加新产品时只需添加对应的工厂类。
缺点:对于产品族的情况处理比较复杂。
适用于产品种类较多且经常变动的场景。
抽象工厂模式提供一个接口,用于创建相关或依赖的家族,而不需要明确指定具体类。它是在工厂方法模式的基础上进一步抽象,用于创建多个相关联的产品。
以游戏人物角色为例,定义了载具、食物、武器等抽象类,具体实现类为不同种族的角色对应的载具、食物、武器。抽象工厂类AbstractFactory
定义了创建载具、食物、武器的方法,具体工厂类实现这些方法。
// 抽象类
public abstract class Vehicle {
abstract void go();
}
public abstract class Food {
abstract void printName();
}
public abstract class Weapon {
abstract void wave();
}
// 具体实现类
public class Car extends Vehicle {
@Override
public void go() {
System.out.println("[人类]-载具-汽车...");
}
}
public class Bread extends Food {
@Override
public void printName() {
System.out.println("[人类]-食物-面包...");
}
}
public class BroadSword extends Weapon {
@Override
public void wave() {
System.out.println("[人类]挥动大刀...");
}
}
// 抽象工厂类
public abstract class AbstractFactory {
abstract Vehicle getVehicle();
abstract Food getFood();
abstract Weapon getWeapon();
}
// 具体工厂类
public class EarthManFactory extends AbstractFactory {
@Override
Vehicle getVehicle() {
return new Car();
}
@Override
Food getFood() {
return new Bread();
}
@Override
Weapon getWeapon() {
return new BroadSword();
}
}
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证使用方始终只使用同一个产品族中的对象。
缺点:产品族扩展困难,增加一个系列的某个产品时,需要修改抽象工厂和抽象产品的代码,不符合开闭原则。
适用于产品族较多且产品之间存在关联的场景,例如不同品牌的产品系列(如苹果的手机、平板、电脑等)。
在电商支付场景中,简单工厂模式可以用于创建不同的支付方式。例如,支付方式包括微信支付、支付宝支付和银行卡支付。通过一个工厂类来根据用户的选择创建对应的支付对象。
// 抽象产品类
public interface Payment {
void pay();
}
// 具体产品类
public class WeChatPay implements Payment {
@Override
public void pay() {
System.out.println("微信支付完成");
}
}
public class Alipay implements Payment {
@Override
public void pay() {
System.out.println("支付宝支付完成");
}
}
public class BankCardPay implements Payment {
@Override
public void pay() {
System.out.println("银行卡支付完成");
}
}
// 工厂类
public class PaymentFactory {
public static Payment getPayment(String type) {
if ("wechat".equalsIgnoreCase(type)) {
return new WeChatPay();
} else if ("alipay".equalsIgnoreCase(type)) {
return new Alipay();
} else if ("bankcard".equalsIgnoreCase(type)) {
return new BankCardPay();
}
return null;
}
}
在电商支付中,工厂方法模式可以用于创建不同的支付工厂,每个工厂负责创建一种支付方式。这种方式更符合开闭原则,便于扩展新的支付方式。
// 抽象工厂类
public interface PaymentFactory {
Payment createPayment();
}
// 具体工厂类
public class WeChatPayFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new WeChatPay();
}
}
public class AlipayFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new Alipay();
}
}
public class BankCardPayFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new BankCardPay();
}
}
在电商支付中,抽象工厂模式可以用于创建支付产品族。例如,支付方式和退款方式是一对关联的产品。通过抽象工厂模式,可以确保使用同一支付方式的退款方式也是一致的。
// 抽象产品类
public interface Payment {
void pay();
}
public interface Refund {
void refund();
}
// 具体产品类
public class WeChatPay implements Payment {
@Override
public void pay() {
System.out.println("微信支付完成");
}
}
public class WeChatRefund implements Refund {
@Override
public void refund() {
System.out.println("微信退款完成");
}
}
public class Alipay implements Payment {
@Override
public void pay() {
System.out.println("支付宝支付完成");
}
}
public class AlipayRefund implements Refund {
@Override
public void refund() {
System.out.println("支付宝退款完成");
}
}
// 抽象工厂类
public interface PaymentFactory {
Payment createPayment();
Refund createRefund();
}
// 具体工厂类
public class WeChatPaymentFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new WeChatPay();
}
@Override
public Refund createRefund() {
return new WeChatRefund();
}
}
public class AlipayFactory implements PaymentFactory {
@Override
public Payment createPayment() {
return new Alipay();
}
@Override
public Refund createRefund() {
return new AlipayRefund();
}
}
工厂设计模式是一种非常实用的设计模式,它通过封装对象的创建过程,使得对象的创建与使用分离,从而提高了系统的可扩展性和可维护性。简单工厂模式适合产品种类较少的场景;工厂方法模式适合产品种类较多且经常变动的场景;抽象工厂模式适合产品族较多且产品之间存在关联的场景。在实际开发中,可以根据具体需求选择合适的工厂模式来实现功能。