如何赋予派生类创建适当对象的责任。(how derived classes can be given the responsibility of creating appropriate objects.)
工厂方法模式(Factory Method Pattern)
:
应用场景:
比如,C++常常采用下面的方式创建对象:
1 | SomeClass someClassObject_1 = SomeClass(); //栈中分配 |
上述方法的问题在于,使用SomeClass的对象的代码现在突然变得依赖于SomeClass的具体实现。使用new创建对象没有什么错,但是它带有将我们的创建对象的代码和具体实现的代码紧密耦合起来了。
这违反了原则“对接口而不是针对实现编程”。(code to an interface and not to an implementation.)这句话也就是说尽量在有需求来的时候,我们类中实现的代码尽量不要变化,而是通过各种接口的组合来解决新需求。
举个例子,如果创建对象需要一系列复杂的初始化操作,比如需要关联其他成员,查配置文件,查数据库表,这时候该怎么办?
如果都写到构造函数里面,那构造函数就会很长很长,代码可读性也不好。
那么比较好的方式是什么呢?计算机里面解决问题的方法就是加一个层。我们就加一个专门的层——工厂类,来专门负责对象的创建工作。
形式上,工厂方法被定义为以下形式:
The class diagram consists of the following entities:
Product
:抽象产品角色。Concrete Product
:具体产品角色,工厂方法模式所创建的任何对象都是这个角色的实例。Creator
:工厂类角色,工厂方法模式的核心,含有与应用紧密相关的商业逻辑。工厂类在客户端的直接调用下创建产品对象。Concrete Creator
:具体工厂类角色。让我们继续制造飞机的过程吧!假设我们正在尝试为F-16战斗机建模。client代码需要为喷气式战斗机构造引擎并进行试飞。
该类的简单实现将如下所示:
1 | class F16 { |
在上面的代码中,我们建造飞机时候使用F16类的具体实现。这时候突然飞机的版本要更新了,我们也要建造它,肯定需要在程序中对新版本的飞机进行表达,这时候该怎么办呢?
我们来说说第二种方法。首先,假设我们要表示F16的A变体和B变体,那么代码看起来像:
1 | class F16SimpleFactory { |
上面是简单工厂模式
的示例,但是上面这种代码还不是模式,而应该算作常见的编程习惯。
您也可以将make方法标记为static,以跳过工厂对象创建步骤(意思是直接通过类名加静态方法来进行调用,而不是在对象中进行封装)。 但是,由于静态方法不能在子类中覆盖,因为它们是类的唯一方法,因此我们将不能对静态工厂进行子类化。
但是,如果我们希望将F16对象部分的创建保持在同一类中,并且仍然能够引入新的F16变体,则可以对F16进行子类化,并将正确的F16变体对象的创建委托给子类处理。 那么这个新方法正是工厂方法模式! 这里的方法是makeF16(),我们将使其表现得像产生适当F16变体的工厂。 让我们继续前进,我们引入了两个这样的子类:
1 | class F16 { |
看上面的代码,我们使用子类继承,然后在子类中实现特殊化的引擎对象。 工厂方法可以提供也可以不提供默认或通用的实现,但是可以通过覆盖create / make方法来使子类专门化或修改产品。 在我们的示例中,变体模型仅具有不同的发动机,但座舱相同。 客户端代码现在可以使用更新的模型,如下所示:
1 | class Client { |
请注意,工厂模式是借助抽象类和多态来实现的, 在我们的情况下,父类F16不知道它是从makeF16()方法返回的F16的哪个变体。 一般设置是超类具有除创建方法之外的所有方法的实现。 create方法可以是抽象方法,也可以带有默认实现,然后由超类的其他方法调用。 正确的对象的创建是子类的责任。
简单工厂模式和静态工厂模式的区别
设计模式之 “工厂模式”
设计模式总结
Software Design Patterns: Best Practices for Software Developers /github educative
Update your browser to view this website correctly. Update my browser now