工厂模式也是一种十分常见的模式,当谈论到工厂模式时,通常指的是工厂方法模式和抽象工厂模式(其实并不包含简单工厂模式),它们都是创建型设计模式,用于对象创建的不同方案。
工厂模式是一种常见的设计模式,它的作用主要有以下几点:
1.封装对象创建过程:工厂模式将对象的创建过程封装在一个单独的类中,客户端无需关心具体的创建细节,只需通过工厂类来获取所需的对象。这样可以隐藏对象创建的细节,降低了客户端与具体类之间的耦合度。
2.简化对象的使用:客户端无需知道如何创建对象,只需调用工厂提供的方法即可获取所需对象,使得客户端代码更加简洁和易于维护。
3.集中控制对象的创建:通过工厂模式,可以将对象的创建集中管理,便于统一管理和维护,例如可以在工厂类中添加缓存、对象池等机制来优化对象的创建和销毁。
4.解耦客户端和具体类:工厂模式可以将客户端代码与具体类解耦,客户端只依赖于工厂接口或抽象类,而不依赖于具体的类实现。这样可以方便替换具体的类实现,提高了代码的灵活性和可扩展性。
5.支持更复杂的对象创建:在工厂模式中,可以根据不同的条件或参数来创建不同的对象,从而实现更复杂的对象创建逻辑,例如根据用户类型来创建不同的用户对象。
总的来说,工厂模式通过封装对象的创建过程,简化了客户端的代码,降低了系统的耦合度,提高了代码的灵活性和可维护性,是一种常用的设计模式。
简单工厂模式
虽然简单工厂模式在设计模式中可能并不被视为一种正式的工厂模式,但从功能和实现上来说,它是一种特殊的工厂模式。
直接上代码
比如我们先定义一个产品接口,具体有哪些产品还不知道,但是有一个创建产品的方法
public interface Product {
void createProduct();
}
这时确定了一款产品A,添加产品A
public class ProductA implements Product {
@Override
public void createProduct() {
// 这里一般用来处理相关业务逻辑
System.out.println("Product A is created");
}
}
又来了一款产品B
public class ProductB implements Product {
@Override
public void createProduct() {
// 这里一般用来处理相关业务逻辑
System.out.println("Product B is created");
}
}
现在我们需要一个工厂类来根据客户端的输入创建不同的产品对象,从而隐藏了对象创建的细节,让客户端更加简单地使用对象
public class ProductFactory {
public static Product createProductA() {
return new ProductA();
}
public static Product createProductB() {
return new ProductB();
}
// 还有一种写法
public static Product createProduct(String productName) {
if ("A".equals(productName)) {
return new ProductA();
} else if ("B".equals(productName)) {
return new ProductB();
}
return null;
}
}
然后具体的使用
public static void main(String[] args) {
Product productA = ProductFactory.createProductA();
productA.createProduct();
Product productB = ProductFactory.createProductB();
productB.createProduct();
Product productB1 = ProductFactory.createProduct("B");
productB1.createProduct();
}
}
执行一下
上面这个就是一个简单工厂模式,将对象的创建过程封装在一个工厂类中,客户端无需知道具体的对象创建细节,只需通过工厂类来获取所需的对象。这样可以使得客户端代码更加简洁、灵活,并且与具体的产品类解耦。缺点就是每添加一种产品我们就需要去修改工厂类。
工厂方法模式
工厂方法模式定义了一个用于创建对象的接口,但将实际创建对象的过程延迟到子类中。这样可以让子类决定要实例化的具体类,从而实现了对对象创建过程的封装。
特点:
1.工厂方法模式定义了一个抽象的工厂接口,该接口声明了一个工厂方法,用于创建产品对象。
2.具体的工厂类实现了工厂接口,并负责创建特定类型的产品对象。
3.客户端通过工厂接口调用工厂方法来创建产品对象,而无需直接实例化具体的产品类。
优点:
1.符合开闭原则:新增产品类型时,只需添加对应的具体工厂类和具体产品类,无需修改现有代码。
2.提高代码可维护性:每个具体工厂类只负责创建特定类型的产品对象,符合单一职责原则,易于理解和维护。
还是直接上代码
一样的首先我们只知道有一个产品
public interface Product {
void createProduct();
}
然后来了产品A
public class ProductA implements Product {
@Override
public void createProduct() {
System.out.println("Product A is created");
}
}
又来了一个产品B
public class ProductB implements Product {
@Override
public void createProduct() {
System.out.println("Product B is created");
}
}
接下来一样的我们需要一个工厂类,但是这里跟简单工厂不一样,我们将工厂也抽象了
public interface Factory {
Product createProduct();
}
然后我们再去创建A产品的工厂
public class ProductAFactory implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
再创建B产品的工厂
public class ProductBFactory implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}
一样的我们测试一下
public class Test {
public static void main(String[] args) {
// Product productA = ProductFactory.createProductA();
// productA.createProduct();
//
// Product productB = ProductFactory.createProductB();
// productB.createProduct();
//
// Product productB1 = ProductFactory.createProduct("B");
// productB1.createProduct();
Factory factoryA = new ProductAFactory();
Product productA = factoryA.createProduct();
productA.createProduct();
Factory factoryB = new ProductBFactory();
Product productB = factoryB.createProduct();
productB.createProduct();
}
}
执行一下
通过比较可以发现,工厂方法模式和简单工厂模式比其实就是把工厂类也抽象了,然后再实现具体的工厂类(比如ProductAFactory和ProductBFactory),这样做的好处就是后面再来个产品C,我们不需要再去修改原有的工厂类,只需要重新添加ProductCFactory就可以了
抽象工厂模式
抽象工厂模式提供了一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。抽象工厂模式通过引入一个抽象工厂接口和多个抽象产品接口,实现了一组相关产品对象的创建。
特点:
1.抽象工厂模式定义了一个抽象工厂接口,该接口声明了一组用于创建产品对象的方法。
2.具体的工厂类实现了抽象工厂接口,并负责创建一组相关产品对象。
3.每个具体的工厂类负责创建特定类型的产品对象,保持产品对象之间的一致性和关联性。
优点:
1.提供一组相关产品对象的创建:抽象工厂模式可以创建一组相关或相互依赖的产品对象,保持产品对象之间的一致性。
2.更好的扩展性:可以轻松地添加新的具体工厂类和具体产品类,以支持新的产品类型。
因为抽象工厂有一点点复杂,它不是用来生产单一的产品的,而是一系列产品,下面我将用两类产品来演示这个抽象工厂的用法
直接上代码
首先我需要士兵,士兵包含很多种类(步兵、骑兵等)
// 士兵
public abstract class Soldier {
abstract void printName();
}
然后我需要一个具体的步兵
// 步兵
public class Infantry extends Soldier {
@Override
void printName() {
System.out.println("步兵");
}
}
再来一个骑兵
// 骑兵
public class Cavalry extends Soldier {
@Override
void printName() {
System.out.println("骑兵");
}
}
这里有一点要注意,细心的人可能会发现这里用的是 abstract 而不是 interface ,注意这里不是因为是抽象工厂所以才用 abstract 来表示抽象,其实这里用 interface也是可以的
这个只是语义问题:形容词用接口,名词用抽象类
好了我们继续来完善抽象工厂,上面已经有了一个骑兵和步兵,它们的区别除了有马和无马外一般武器也是不一样的
所以我们再来一个武器
// 武器
public abstract class Arms {
abstract void printName();
}
我们这里来个刀
// 刀
public class Sword extends Arms {
@Override
void printName() {
System.out.println("刀");
}
}
再来个矛
// 矛
public class Spear extends Arms {
@Override
void printName() {
System.out.println("矛");
}
}
好了基础士兵和武器都有了,我们现在需要一个工厂来进行批量配置士兵和武器
我们先抽象一个工厂出来,这个工厂生产士兵和士兵对应的武器
public abstract class AbstractFactory {
abstract Soldier createSoldier();
abstract Arms createArms();
}
然后我们现在指定步兵配刀,所以我们再来一个步兵工厂
public class InfantryFactory extends AbstractFactory {
@Override
Soldier createSoldier() {
return new Infantry();
}
@Override
Arms createArms() {
return new Sword();
}
}
再来一个骑兵工厂,骑兵配矛
public class CavalryFactory extends AbstractFactory {
@Override
Soldier createSoldier() {
return new Cavalry();
}
@Override
Arms createArms() {
return new Spear();
}
}
测试一下
public class Test {
public static void main(String[] args) {
AbstractFactory af1 = new InfantryFactory();
af1.createSoldier().printName();
af1.createArms().printName();
AbstractFactory af2 = new CavalryFactory();
af2.createSoldier().printName();
af2.createArms().printName();
}
}
运行一下
我这样写不知道大家能不能理解,就是这里的工厂不再是处理单一的产品,而是处理一系列产品,比如步兵配刀骑兵配枪,后面我可能还需要给步兵配盾骑兵配弓箭什么的,这里工厂是用来生产一系列配套产品的