当创建一组相互之间有关系的类时,在对象创建期间维护他们之间的这些关系是很重要的。要做到这一点,有一个办法是使用工厂方法Factory Method 设计模式。工厂方法模式是一个创建模式,解决了在没有指定具体类型的情况下创建对象的问题。这经常用在抽象类上,专为创建对象定义一个方法。子类就可以覆盖这个方法来定义要创建的特定对象。
工厂方法模式经常与另一个称为模板方法的模式协作,要更好地理解工厂方法并提供更多的上下文含义,我们也将了解模板方法模式。因为工厂方法利用并建立于相同的概念之上,所以我们将首先了解模板方法模式。
抽象类
抽象类在工厂方法和模板方法模式中扮演主要角色。虽然ActionScript 3.0 并不支持抽象类和抽象方法,但是我们依然可以使用抽象类和抽象方法的概念。一个抽象类是这样的一个类,他总是用来被继承,并从不直接实例化。它的用法与接口相似, 但是有一个主要的区别: 一个接口定义只有公有的方法签名,但是一个抽象类的定义既有接口也有执行。一个抽象类使用抽象方法,他没有什么功能,仅仅作为占位符使用。在其他语言中,如C#以及Java, 你可以使用关键字abstract 定义抽象方法,他告诉子类必须覆盖这个方法。因为ActionScript 3.0并没有一个abstract 关键字,所以你可以考虑一个惯用的方法,那就是在抽象方法内部抛出一个异常。这个方式在编译时不会抛出错误,但是在运行时会。底线是ActionScript 3.0没有确定的途径来强制抽象方法。
关于在ActionScript 3.0中使用抽象类,你必须知道两个关键字。第一个是override 关键字。子类必须使用这个关键字来覆盖定义在基类中的抽象方法。他们的方法签名也必须严格匹配。
另一个关键字是final。这个关键字用在抽象类定义的方法上,使得他的子类无法覆盖这个方法。当我们定义模板方法Template Method模式的时候,我们将使用final 关键字。
模板方法Template Method
模板方法是定义在抽象类中的抽象方法,他放置一套普通的算法来填充(至少是部分)抽象方法。算法的定义是在子类覆盖抽象方法的时候完成的。算法的组织结构保存在模板方法中。
考虑下面的例子,我们有一个抽象类,他定义游戏初始化的方式:
package factoryexample {
public class AbstractGame {
// 模板方法
public final function initialize():void {
createField();
createTeam("red");
createTeam("blue");
startGame();
}
public function createField():void {
throw new Error("抽象方法!");
}
public function createTeam(name:String):void {
throw new Error("抽象方法!");
}
public function startGame():void {
throw new Error("抽象方法!");
}
}
}
在上面的例子中,initialize() 方法就是模板方法。他定义了游戏如何被初始化,首先调用createField() 方法,然后调用createTeam()方法创建组,最后调用startGame() 方法开始游戏。他调用的方法在这个类中并没有定义功能。这些是子类的任务,由子类来定义如何创建场地和如何创建组以及游戏如何开始等等。并且所有的子类都只能够按照这种方式来初始化,因为该模板方法是申明为final属性的,不可被覆盖,也就意味着不会被更改。
现在我们将创建一个FootballGame 类,他将扩展我们的AbstractGame 类。这个子类覆盖抽象方法,该抽象方法被抽象基类中的initialize() 模板方法调用。
package factoryexample {
public class FootballGame extends AbstractGame {
public override function createField():void {
trace("创建足球场地");
}
public override function createTeam(name:String):void {
trace("创建足球队: " + name);
}
public override function startGame():void {
trace("开始足球游戏");
}
}
}
可以看出, FootballGame 类覆盖了 createField(), createTeam()以及 startGame() 等方法,使他们特定于足球游戏。但是,初始化的算法被保留了。同样的技术也可以用来创建一个BaseballGame 或者BastketballGame 类。我们可以用下面的代码来运行这个例子:
package factoryexample {
import factoryexample.FootballGame;
import flash.display.Sprite;
public class FactoryExample extends Sprite {
public function FactoryExample() {
// 创建一个 FootballGame实例
var game:FootballGame = new FootballGame();
// 调用定义在 AbstractGame中的模板方法
game.initialize();
}
}
}
下面显示的是输出面板中的内容。
创建足球场地
创建足球队:红队
创建足球队:蓝队
开始足球游戏
你可以看到,子类中覆盖的方法通过模板方法被调用了。算法保留在模板方法中,而具体的执行细节却遵循子类方法。
工厂方法Factory Method
不用很费神,现在我们可以从前面的模板方法例子转到工厂方法例子了。执行模板方法中的工厂方法是很普通的。
在前面的模板方法例子中,我们的createField() 方法并未返回任何东西,他只是跟踪输出短语 "创建足球场地"。让我们来更新他,使他可以创建并返回一个场地对象。因为不同的游戏有不同的场地类型,所以我们将创建一个接口,名叫IField。所有的场地类都将执行他。我们的接口将只定义一个名叫drawField()的方法:
package factory {
public interface IField {
function drawField():void;
}
}
}
现在我们将建立一个FootballField 类来执行IField 接口。为了不跑题,我们将不会实际绘制一个足球场在舞台上,但是可以由你自己来完成。这里是FootballField 类的基本定义:
package factoryexample {
import factoryexample.IField;
public class FootballField implements IField {
public function drawField():void {
trace("正在绘制足球场地");
}
}
}
工厂模式Factory Method的目的是连接两个或更多独立的但又有关系的类层次结构。第一个类层次结构是AbstractGame 类和他的子类: FootballGame, BaseballGame以及 BastketballGame。我们的第二个类层次结构是现在的IField接口和执行他的类: FootballField, BaseballField以及 BasketballField。AbstractGame 和IField 对象是有关系的,但是这些特定对象的创建却是由该游戏的子类决定的。图5.1展示这些类层次结构。
图 5.1. Factory Method 例子中的类层次结构
现在我们可以重新编写AbstractGame类中的createField() 方法和initialize() 方法以反映IField 对象的存在。我们的createField() 方法现在就是一个工厂方法Factory Method,他返回一个执行IField 接口的对象。initialize() 方法现在可以更进一步调用IField 对象的drawField() 方法:
package factoryexample {
import factoryexample.IField;
public class AbstractGame {
//模板方法Template Method,final关键字的使用,使得所有子类的initialize()方法都完全一样(无法进行覆盖),就像“一个模子刻下来的”一样。
public final function initialize():void {
var field:IField = createField();
field.drawField();
createTeam("red");
createTeam("blue");
startGame();
}
//工厂方法Factory Method
public function createField():IField{
throw new Error("抽象方法!");
}
public function createTeam(name:String):void {
throw new Error("抽象方法!");
}
public function startGame():void {
throw new Error("抽象方法!");
}
}
}
这个抽象类和模板算法还是完全没有特定功能,特定对象的创建还是要靠子类来完成。让我们重新编写FootballGame 类,现在可以让他创建并返回一个FootballField 对象:
package factory {
import factory.FootballField;
import factory.IField;
public class FootballGame extends AbstractGame {
public override function createField():IField {
return new FootballField();
}
public override function createTeam(name:String):void {
trace("创建足球队: " + name);
}
public override function startGame():void {
trace("开始足球游戏");
}
}
}
如果我们运行这个例子,我们将获得这些输出内容:
正在绘制足球场地
创建足球队:红对
创建足球队:蓝色
开始足球游戏
简单工厂方法Simple Factory
工厂方法Factory Method经常被误会。 我们经常听到有人说他的代码是按照工厂方法Factory Method模式编写的,仔细审查了这些代码后发现,他们实际上并不是真正的工厂方法Factory Method。过去我们也经常犯这样的错误: 编写一个像下面这样的类,并认为他就是一个工厂方法Factory Method:
package factoryexample {
public class GameFactory {
public static function createGame(gameType:String):IGame {
switch(gameType){
case "football":
return new FootballGame();
case "baseball":
return new BaseballGame();
case "basketball":
default:
return new BasketballGame();
}
}
}
}
如果你认为这就是一个工厂方法,那么请你打消这个念头。因为Factory Method 比这个要复杂得多。实际上上面这个例子根本不是一个设计模式。他通常被称为简单工厂Simple Factory 或参数化工厂方法Parameterized Factory。并不是说她就没有用,实际上我们将在第12章使用这项技术, "状态模式", 基于名称设置状态。
总结
抽象类是面向对象设计中的一个非常重要的工具。他们普遍用在类库和框架方面,因为他们是跨子类提取公共行为的可靠途径。
在你使用抽象类的时候,模板方法和工厂方法设计模式就是最适合的,也很方便。模板方法允许你创建一个带有普遍性的公共算法,他的特定步骤将由具体的子类来定义。工厂方法允许你触发抽象类中对象的创建,但是将特定类型的对象的创建指向子类。
相关推荐
在软件设计模式的世界里,工厂模式和模板方法模式是两种常用的设计模式,它们都有各自的优点和应用场景。这两种模式都是面向对象设计原则的体现,能够帮助我们编写出更加灵活、可扩展的代码。让我们来深入探讨一下这...
处理层的设计采用了设计模式中的策略模式、模板方法模式和工厂模式。 Server端和Client端的实现也采用了分层的设计方式,包含自定义的模型层、视图层和控制层。 说明:程序采用配置文件的方式进行初始化,运行时时请...
本篇文章将对三种主要的工厂模式:简单工厂、工厂方法和抽象工厂进行深入的对比和总结。 **简单工厂模式** 是最基础的工厂模式形式,它提供一个静态方法或类来创建对象。在这个模式中,工厂是负责创建对象的中心...
### 深入浅出设计模式之模板方法模式 #### 一、模板方法模式概述 设计模式是软件工程中一种非常重要的技术手段,...在实际开发过程中,合理运用模板方法模式可以帮助我们更好地组织代码,提高程序的灵活性和扩展性。
模板方法模式是设计模式中行为模式的一种,它在软件工程中扮演着重要的角色,尤其是在创建算法框架时。这种模式允许我们在抽象类中定义一个算法的骨架,而将一些步骤延迟到子类中实现,使得子类可以不改变算法的结构...
模板方法模式是设计模式中行为型模式的一种,它在软件工程中扮演着非常重要的角色,尤其是在Java编程中。模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。它允许子类不改变一个算法的结构即可重...
模板方法模式是设计模式中的一种行为模式,它在软件工程中扮演着重要的角色,尤其是在C++这样的面向对象编程语言中。这种模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的...
模板方法模式是面向对象设计中的一种行为设计模式,它在软件工程中扮演着重要的角色,尤其是在需要维护代码的可扩展性和可复用性时。这个模式的核心思想是封装不变的部分,将可变部分抽象出来,让子类进行扩展。通过...
本案例主要探讨了三种经典的设计模式:抽象工厂模式、工厂方法模式和策略模式,并以手机加工厂为实际应用场景进行阐述。 首先,**抽象工厂模式**是创建型设计模式之一,它提供一个接口,用于创建相关或依赖对象的...
装饰者模式和模板方法模式是两种在软件设计中常见的行为设计模式,它们分别在不同的场景下发挥着重要的作用。在本案例中,我们将探讨如何将这两种模式应用到一个奶茶商店的系统中,以便引入咖啡产品。 首先,让我们...
3. Qt工厂模式工程 4. Qt工厂模式例程 5. Qt工厂模式例子 6. 简单工厂模式 部分源码实例: // 奔驰工厂 class BenzFactory : public AFactory { public: ICar* CreateCar() { return new BenzCar(); } }; // ...
抽象工厂模式、建造模式、工厂方法模式、原型模式、单例模式、外观模式、适配器模式、桥接模式、组合模式、装饰模式、享元模式、代理模式、命令模式、解释器模式、访问者模式、迭代子模式、中介者模式、备忘录模式、...
本示例中的"qt5编写的使用模板类工厂模式画图程序"聚焦于Qt5库的应用,结合了工厂模式和模板视图概念来高效地创建和管理图形界面中的元素。下面将详细介绍这两个关键知识点。 **工厂模式** 工厂模式是一种创建型...
本篇文章将深入探讨两种重要的设计模式:策略模式和模板模式。通过理解这两种模式,开发者可以更好地组织代码,提高代码的灵活性和可扩展性。 ### 策略模式 策略模式是一种行为设计模式,它使你能在运行时改变对象...
模板方法模式的优点包括代码结构清晰、易于维护和扩展,因为它强制了算法的整体结构,同时允许子类对算法的某个步骤进行定制。然而,过度使用模板方法可能导致设计过于僵化,不利于进一步的扩展。因此,应当谨慎地...
1. **抽象类(Abstract Class)**:这是模板方法模式的核心,它定义了模板方法和一系列基本操作。其中,模板方法是一个具体方法,它给出了一个算法的骨架;而基本操作通常包括具体方法(Concrete Method)、抽象方法...
python 项目里常用的设计模式 单例模式 组合模式 策略模式 抽象工厂 代理模式 工厂模式 观察者模式简单工厂 建造者模式 模板模式 桥接多维度 桥接模式 适配器模式 外观模式 享元模式 责任链组合模式
模板方法模式是设计模式中的一种行为模式,它在软件工程中扮演着重要的角色,尤其是在创建算法骨架时。这种模式允许我们在父类中定义一个算法的框架,而将具体步骤延迟到子类中实现,从而实现了代码复用和扩展。下面...
3. **模板方法模式-考试题目03**:可能涵盖模板方法模式与其他设计模式的对比,如策略模式、工厂模式,或者在多态性和封装方面的应用。 4. **模板方法模式-基本代码**:这个文件应该提供了一些代码示例,展示如何在...
c++设计模式-行为型模式-模板方法模式;qt工程;c++简单源码; 模板方法(Template Method)模式的定义如下:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重...