详细介绍设计模式之工厂模式

作者: wulilele 分类: 编程技术 发布时间: 2023-05-05 08:53

工厂模式是一种常用的面向对象设计模式,它对对象的创建进行了抽象,解决了创建对象过程中的一些复杂性问题。

举个例子,假设我们要开发一个游戏,游戏中有很多角色需要创建,比如战士、法师、盗贼等等,这些角色拥有各自不同的属性和技能。如果我们直接在代码中写死每个角色的创建过程,那么以后如果有新的角色加入或者某个角色的属性改变了,都需要修改代码,非常麻烦。

这时候我们就可以使用工厂模式来抽象出角色创建的过程,让代码更加灵活和易于维护。

工厂模式的核心思想是:定义一个接口或抽象类,用于创建对象的方法被实现类继承,在实现类中实现具体的创建过程。这样在客户端中只需要调用工厂的方法就可以获得所需的对象,而无需关心对象的具体创建过程。

下面是一个简单的示例代码:

定义角色的抽象类

abstract class Role {
    public abstract void show();
}

定义角色的具体类

class Warrior extends Role {
    public void show() {
        System.out.println(\"我是战士\");
    }
}

class Mage extends Role {
    public void show() {
        System.out.println(\"我是法师\");
    }
}

class Thief extends Role {
    public void show() {
        System.out.println(\"我是盗贼\");
    }
}

定义角色实例化的工厂类

class RoleFactory {
    public static Role getRole(String roleType) {
        if (roleType == null) {
            return null;
        }
        if (roleType.equalsIgnoreCase(\"warrior\")) {
            return new Warrior();
        } else if (roleType.equalsIgnoreCase(\"mage\")) {
            return new Mage();
        } else if (roleType.equalsIgnoreCase(\"thief\")) {
            return new Thief();
        }
        return null;
    }
}

客户端调用示例

public class Client {
    public static void main(String[] args) {
        Role role1 = RoleFactory.getRole(\"warrior\");
        role1.show(); // 输出:我是战士

        Role role2 = RoleFactory.getRole(\"mage\");
        role2.show(); // 输出:我是法师

        Role role3 = RoleFactory.getRole(\"thief\");
        role3.show(); // 输出:我是盗贼
    }
}

可以看到,客户端只需要调用工厂的getRole方法,就可以获取到所需的角色实例,而具体的角色创建过程则被隐藏在工厂类中,对于客户端来说是透明的。

工厂模式可以很好地解耦客户端与具体实现类,让代码更加灵活和易于扩展。如果以后需要新增一种角色,只需要新增一个具体角色类和对应的创建方法即可,不需要修改客户端代码。

与抽象工厂模式的区别

工厂模式和抽象工厂模式都是创建型设计模式,它们都是为了解决对象的创建问题。但是,它们之间有一个重要的区别,即抽象工厂模式更加抽象化,提供了创建一系列相关或依赖对象的接口(工厂)。

工厂模式关注的是单个对象的创建,它封装了对象的创建过程,客户端只需要知道需要什么对象,调用工厂的方法,就可以获取所需的对象。例如上面所示的角色创建的示例。

而抽象工厂模式则是针对有多个相互依赖或相关的对象需要创建的情况,它将一系列相关的对象的创建抽象成一个工厂接口,通过这个接口创建一系列对象。换句话说,抽象工厂模式提供了一种抽象化的方式来创建一组相关的对象,它能够隐藏对象的创建细节,提供一个简单易用的接口,让客户端只需要知道如何调用这个接口,而不需要关心具体实现。下面我们来看一个例子:

假设我们需要创建一组界面设计工具,包括Button、TextField和ComboBox三种控件,并且不同风格的界面设计工具之间有相互依赖或相关。我们可以定义一个抽象工厂接口,让每个具体的工厂实现这个接口:

interface GUIFactory {
    Button createButton();
    TextField createTextField();
    ComboBox createComboBox();
}

然后我们可以定义不同的具体工厂来实现这个接口,例如Windows风格的工厂:

class WindowsFactory implements GUIFactory {
    public Button createButton() {
        return new WindowsButton();
    }
    public TextField createTextField() {
        return new WindowsTextField();
    }
    public ComboBox createComboBox() {
        return new WindowsComboBox();
    }
}

和Mac风格的工厂:

class MacFactory implements GUIFactory {
    public Button createButton() {
        return new MacButton();
    }
    public TextField createTextField() {
        return new MacTextField();
    }
    public ComboBox createComboBox() {
        return new MacComboBox();
    }
}

然后我们可以根据使用者的需要来选择相应的工厂来创建界面组件:

GUIFactory factory;
if (osName.equalsIgnoreCase(\"Windows\")) {
    factory = new WindowsFactory();
} else if (osName.equalsIgnoreCase(\"Mac\")) {
    factory = new MacFactory();
}

这种方式下,每个具体的工厂实现了同一个接口,通过这个接口的方法来创建一组相关的对象,每个对象的创建都由具体的工厂负责,使用者只需要选择需要使用的工厂即可,同样能够隐藏对象的创建细节,提供一个简单易用的接口。

综上所述,工厂模式和抽象工厂模式虽然都是为了解决对象的创建问题,但它们所解决的问题不同,工厂模式将单个对象的创建进行抽象,而抽象工厂模式则将一系列相关对象的创建进行抽象。

百度未收录