工厂方法模式
工厂方法模式
什么是工厂方法模式
工厂方法模式(Factory Pattern)是 Java 中最常用的设计模式之一。工厂方法模式提供了一种创建对象的方式,而无需指定要创建的具体类。使得创建对象的过程与使用对象的过程分离。通过使用工厂方法模式,可以将对象的创建逻辑封装在一个工厂类中,而不是在客户端代码中直接实例化对象,这样可以提高代码的可维护性和可扩展性。
工厂方法模式的结构:
工厂方法模式的创建
现在我们以运动包含跑步和游泳为例,创建一个工厂方法模式:
1、创建共同的接口
public interface Sports {
void sport();
}
2、创建不同的实现类
public class Run implements Sports{
@Override
public void sport() {
System.out.println("跑步");
}
}
public class Swim implements Sports{
@Override
public void sport() {
System.out.println("游泳");
}
}
3、创建接口工厂类
public class SportsFactory {
public Sports getSport(String sportType) {
if (sportType == null) {
return null;
}
if (sportType.equals("run")) {
return new Run();
} else if (sportType.equals("swim")) {
return new Swim();
}
return null;
}
}
4、测试
public class Test {
public static void main(String[] args) {
SportsFactory sf = new SportsFactory();
//根据输入获取跑步对象
Sports run = sf.getSport("run");
run.sport();
//获取游泳对象
Sports swim = sf.getSport("swim");
swim.sport();
}
}
可以看出,在工厂方法模式中,用户不会显式地创建不同类别的实例,而是通过传入字符串来指定对象的类别。
抽象工厂模式
什么是抽象工厂模式
抽象工厂之于普通工厂相当于普通工厂之于具体的实现类,也就是工厂的工厂;抽象工厂和普通工厂是父子关系,每个普通工厂都是抽象工厂的子类;抽象工厂中抽象出了不同工厂的get方法,便于在工厂选择器中选择需要使用的工厂。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂方法模式提供对象。抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定具体实现类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。
抽象工厂的结构:
抽象工厂的实现
我们以活动作为抽象工厂,普通工厂为运动和唱歌,运动工厂对应的实现类仍然为跑步和游泳,唱歌工厂对应的实现类为唱中文歌和唱英文歌。
1、创建普通工厂接口
//运动工厂接口
public interface Sport {
void sport();
}
//唱歌工厂接口
public interface Sing {
void sing();
}
2、创建所有工厂的实现类
//运动工厂中的跑步类
public class Run implements Sport {
@Override
public void sport() {
System.out.println("跑步");
}
}
//运动工厂中的游泳类
public class Swim implements Sport {
@Override
public void sport() {
System.out.println("游泳");
}
}
//唱歌工厂中的唱中文歌类
public class ChineseSongs implements Sing{
@Override
public void sing() {
System.out.println("唱中文歌");
}
}
//唱歌工厂中的唱英文歌类
public class EnglishSongs implements Sing{
@Override
public void sing() {
System.out.println("唱英文歌");
}
}
3、创建抽象工厂类
抽象工厂类中包含获取普通工厂对象的抽象方法。
public abstract class AbstractFactory {
//抽象出两个工厂方法
public abstract Sport getSport(String sport);
public abstract Sing getSing(String song);
}
4、创建工厂选择器
通过传递工厂名称获取普通工厂
public class FactoryProducer {
public static AbstractFactory getFactory(String factory) {
if (factory.equals("运动")) {
return new SportFactory();
} else if(factory.equals("唱歌")) {
return new SingFactory();
}
return null;
}
}
5、扩展普通工厂
这一步是使普通工厂继承抽象工厂,并根据传入的字符串来创建具体的实现类对象。实际上这一步应该在创建工厂选择器之前,本文写在这一步只是为了使步骤三(创建抽象工厂)和步骤四(从抽象工厂中创建工厂)放在一起方便记忆。
public class SportFactory extends AbstractFactory{
@Override
public Sing getSing(String song) {
return null;
}
@Override
public Sport getSport(String sport) {
if (sport == null) {
return null;
} else if (sport.equals("run")) {
return new Run();
} else if (sport.equals("swim")) {
return new Swim();
}
return null;
}
}
public class SingFactory extends AbstractFactory {
@Override
public Sport getSport(String sport) {
return null;
}
@Override
public Sing getSing(String song) {
if (song == null) {
return null;
} else if (song.equals("中文歌")) {
return new ChineseSongs();
} else if (song.equals("英文歌")) {
return new EnglishSongs();
}
return null;
}
}
6、测试
public class Test {
public static void main(String[] args) {
//先通过工厂选择器选择运动工厂
AbstractFactory sportFactory = FactoryProducer.getFactory("运动");
//选择好工厂之后,选择工厂中想创建的的对象
Sport sporter1 = sportFactory.getSport("run");
//调用该对象的方法
sporter1.sport();
Sport sporter2 = sportFactory.getSport("swim");
sporter2.sport();
//创建唱歌工厂
AbstractFactory singFactory = FactoryProducer.getFactory("唱歌");
Sing singer1 = singFactory.getSing("中文歌");
singer1.sing();
Sing singer2 = singFactory.getSing("英文歌");
singer2.sing();
}
}
测试结果如下
总结
1、工厂方法模式优缺点:
- 优点:调用者不需要知道产品的具体实现,只需要关注接口的名称;符合开闭原则,增加产品时创建工厂以及实现类即可,扩展性好。
- 缺点:增加产品步骤繁琐,需要创建工厂和实现类,导致系统中类的数量增加,对于这些类的编译和运行会增加系统开销。
2、抽象工厂模式的优缺点
- 优点:与工厂方法模式相同,调用者不需要知道产品的具体实现;除此之外还能使同一族的对象聚集起来。
- 缺点:比工厂方法模式更加复杂,并且扩展性不好,需要新加产品时需要修改抽象工厂以及工厂选择器。
3、工厂方法模式和抽象工厂模式的区别
- 1、工厂模式主要关注一个对象的创建,而抽象工厂关注的是一系列相似对象的创建;
- 2、当需要根据不同情况创建不同类型的对象时,需要使用工厂模式;当需要将多个系列对象按分类存放时可以使用抽象工厂模式;
- 3、工厂模式的扩展性好,抽象工厂模式的扩展性差。