Java设计模式——工厂设计模式
前言
在了解工厂设计模式前,先要对"产品",“产品组”,“工厂”,OCP(开闭原则),这几个看似很专业的名词进行一定的了解,我将会使用一个小例子贯穿整个工厂设计模式。
对"产品",“产品组”,"工厂"的初步理解
举个栗子
若你作为一名消费者(客户)想要购买一台笔记本电脑,此时
工厂:微软、联想、华硕…(电脑制造厂商)
产品:内存、显卡、CPU中的某一种
产品组:电脑制造厂商想要组装一台可以使用的电脑,该电脑不会由某一件"产品"所组成,而是由产品组(相互之间存在依赖关系的产品的集合)所构成,在这个例子中,产品组就是组装一台电脑所需要的所有零件的集合
对OCP(开闭)原则的初步理解
在设计和代码编写时应当所遵循的开闭原则:在现有代码上以最小的改动为代价来进行新功能的添加,尽可能的在添加新功能的时候不去改动现有的代码——对扩展开放,对修改关闭
一、工厂模式的引入
举个栗子
// 定义一个Computer接口,并定义一个简单的printComputer方法用于输出该电脑的名称
interface Computer {
void printComputer();
}
// 定义Macbook类实现Computer接口
class MacbookProComputer implements Computer {
public void printComputer() {
System.out.println("This is a MacbookPro");
}
}
// 定义SurfaceBook类实现Computer接口
class SurfaceBookComputer implements Computer {
public void printComputer() {
System.out.println("This is a SurfaceBook");
}
}
public class Client {
// 将形参设置为接口,而实参设置为接口的具体实现类
public void buyComputer(Computer computer) {
computer.printComputer();
}
public static void main(String[] args) {
Client client = new Client();
// 不同品牌的电脑需要修改这行代码new的对象
client.buyComputer(new MacbookProComputer());
}
}
如果是上面这种情况,如果此时用户需要买一台华硕电脑,那么除了需要在服务端中添加一个HuaShuoComputer类去实现Computer接口之外,还必须修改客户端的代码,将new MacbookProComputer()改为new HuaShuoComputer()
当产品发布或产品更新后,客户端的代码尽可能的不要改动(添加新功能时),这样的改动严重违反了OCP开闭原则。因此,引入三种工厂模式来解决此类问题。
二、简单工厂模式(没有产品组并且产品个数较少)
1、定义:专门定义一个类(第三方类),用来创建其他类实例(解耦<提取出来>,将客户端创建对象的操作解耦到外部第三方类中),被创建的实例通常都具有共同的父类。
2、实例描述:客户需要购买什么样的电脑,只需要创建一个电脑工厂,并提供对应电脑的编号即可(真正电脑对象的产生将在电脑工厂中进行)
import java.util.Scanner;
interface Computer{
void buyComputer();
}
class MacBookPro implements Computer{
public void buyComputer(){
System.out.println("This is MacBookPro");
}
}
class AlienBook implements Computer{
public void buyComputer(){
System.out.println("This is AlienBook");
}
}
/**
* 创建电脑对应的简单工厂,在该工厂内通过客户端输入的电脑编号,进行对应产品类的实例化
*/
class ComputerFactory{
public Computer buyComputer(String type){
if(type.equals("mac")){
return new MacBookPro();
}else if(type.equals("alien")){
return new AlienBook();
}
return null;
}
}
public class FactoryModelTest{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Please input your choose:");
String type = scanner.nextLine();
ComputerFactory computerFactory = new ComputerFactory();
Computer computer = computerFactory.buyComputer(type);
if(computer!=null){
computer.buyComputer();
}else{
System.out.println("No such computer");
}
}
}
运行结果:
3、组成:
①一个抽象产品类(Computer)
②多个具体产品类(MacBookPro,AlienBook…<Computer的实现类>)
③一个工厂类(ComputerFactory)
4、应用场景:没有产品组且产品个数较少(eg:Spring-BeanFactory)
三、工厂方法模式
1、定义:将简单工厂再次升级,定义一个用来创建对象的接口,让子类决定实例化哪一个工厂。(创建工厂的接口,并创建多个工厂类实现该工厂接口,并在每个工厂类中实例化产品对象,每一个工厂类对应一个产品)
2、实例描述:创建一个电脑工厂的接口,并创建多个工厂类实现该电脑工厂接口,在这些工厂类中分别实例化该工厂所对应的那个产品。客户端会根据具体使用的哪个工厂类而知道创建的什么产品。
/**
* 创建产品接口
*/
interface Computer{
void buyComputer();
}
class MacbookPro implements Computer{
public void buyComputer(){
System.out.println("This is a mac");
}
}
class AlienBook implements Computer{
public void buyComputer(){
System.out.println("This is a alien");
}
}
/**
* 创建工厂接口,并在该接口中定义方法用于实例化产品,将实例化产品延迟到子类中
*/
interface ComputerFactory{
Computer createComputer();
}
/**
* 在工厂接口的实现类中对产品进行实例化
*/
class AppleFactory implements ComputerFactory{
public Computer createComputer(){
return new MacbookPro();
}
}
class MsFactory implements ComputerFactory{
public Computer createComputer(){
return new AlienBook();
}
}
public class FactoryModelTest2{
public static void main(String[] args) {
ComputerFactory computerFactory = new MsFactory();
Computer computer = computerFactory.createComputer();
computer.buyComputer();
}
}
运行结果:
3、组成:
①一个抽象产品类(Computer)
②多个具体产品类(MacBookPro,AlienBook…<Computer的实现类>)
③一个抽象工厂(ComputerFactory)
④多个具体工厂(AppleFactory,MsFactory…<ComputerFactory的实现类>)
4、应用:将产品的实例化延迟到工厂的子类中进行,可根据工厂的类型判断出产品的类型(eg:Spring-FactoryBean)
四、抽象工厂模式
1、定义:提供一个创建一系列相关或相互依赖对象的接口(抽象工厂,多条产品线),而无需指定它们具体的类。(在工厂方法模式的基础上多加几条产品线,将工厂方法模式的一个工厂对应一个产品,转换为一个工厂对应一个产品组<多个产品的组合>)
2、实例描述:在电脑工厂接口中添加选择操作系统的方法,此时的操作系统+电脑品牌构成了一个产品组,而电脑工厂接口,电脑品牌接口,操作系统接口在定义的时候只需要知道它们彼此的关系即可,而不需要知道这些接口具体是怎么实现的。
/**
* 创建产品Computer(电脑类型)接口
*/
interface Computer{
void buyComputer();
}
class MacbookPro implements Computer{
public void buyComputer(){
System.out.println("This is a mac");
}
}
class AlienBook implements Computer{
public void buyComputer(){
System.out.println("This is a alien");
}
}
/**
* 创建产品OperatingSystem(操作系统)接口
*/
interface OperatingSystem{
void printSystem();
}
class MacOsSytem implements OperatingSystem{
@Override
public void printSystem() {
System.out.println("This is a Mac Os");
}
}
class Windows10System implements OperatingSystem{
@Override
public void printSystem() {
System.out.println("This is a windows 10");
}
}
/**
* 创建工厂接口,并在该接口中定义方法用于实例化产品,将实例化产品延迟到子类中
* 一个工厂——>多个产品(产品组)
*/
interface ComputerFactory{
Computer createComputer();
OperatingSystem createSystem();
}
/**
* 在工厂接口的实现类中对多个产品(产品组——相互之间存在关系的产品)进行实例化
*/
class AppleFactory implements ComputerFactory{
public Computer createComputer(){
return new MacbookPro();
}
@Override
public OperatingSystem createSystem() {
return new MacOsSytem();
}
}
class MsFactory implements ComputerFactory{
public Computer createComputer(){
return new AlienBook();
}
@Override
public OperatingSystem createSystem() {
return new Windows10System();
}
}
public class FactoryModelTest3 {
public static void main(String[] args) {
// 一个工厂接口的具体实现类对应一个产品组
ComputerFactory computerFactory = new MsFactory();
Computer computer = computerFactory.createComputer();
OperatingSystem operatingSystem = computerFactory.createSystem();
computer.buyComputer();
operatingSystem.printSystem();
}
}