设计模式之工厂模式
工厂方法模式
- 工厂方法模式
- 什么是工厂方法模式
- 工厂方法模式的创建
- 1、创建共同的接口
- 2、创建不同的实现类
- 3、创建接口工厂类
- 4、测试
- 抽象工厂模式
- 什么是抽象工厂模式
- 抽象工厂的实现
- 1、创建普通工厂接口
- 2、创建所有工厂的实现类
- 3、创建抽象工厂类
- 4、创建工厂选择器
- 5、扩展普通工厂
- 6、测试
- 总结
工厂方法模式
什么是工厂方法模式
工厂方法模式(Factory Pattern)是 Java 中最常用的设计模式之一。工厂方法模式提供了一种创建对象的方式,而无需指定要创建的具体类。使得创建对象的过程与使用对象的过程分离。通过使用工厂方法模式,可以将对象的创建逻辑封装在一个工厂类中,而不是在客户端代码中直接实例化对象,这样可以提高代码的可维护性和可扩展性。
工厂方法模式的结构:
工厂方法模式的创建
现在我们以运动包含跑步和游泳为例,创建一个工厂方法模式:
1、创建共同的接口
public interface Sports {void sport();
}
2、创建不同的实现类
public class Run implements Sports{@Overridepublic void sport() {System.out.println("跑步");}
}
public class Swim implements Sports{@Overridepublic 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 {@Overridepublic void sport() {System.out.println("跑步");}
}
//运动工厂中的游泳类
public class Swim implements Sport {@Overridepublic void sport() {System.out.println("游泳");}
}
//唱歌工厂中的唱中文歌类
public class ChineseSongs implements Sing{@Overridepublic void sing() {System.out.println("唱中文歌");}
}
//唱歌工厂中的唱英文歌类
public class EnglishSongs implements Sing{@Overridepublic 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{@Overridepublic Sing getSing(String song) {return null;}@Overridepublic 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 {@Overridepublic Sport getSport(String sport) {return null;}@Overridepublic 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、工厂模式的扩展性好,抽象工厂模式的扩展性差。