设计模式演练——抽象工厂模式

摘要:
9035年,望星的精英舰队集结在美星附近的轨道上,试图一举拿下美星。大多数喵星人已被转移到防空工程。随着发动机的轰鸣声,战斗机编队已经离开跑道,驶向望星舰队。我们将重新设计它:经过考虑,一个新的设计出现了:抽象工厂模式的常见实现方法是使用工厂方法模式,或者原型模式。

1.小C的故事

       下面讲述的是关于x星系喵星和汪星两个宿敌星球之间的故事。首先把镜头聚焦到喵星,它是主角登场的地方。(本故事纯属虚构,如有雷同,纯属巧合) 
       喵星纪元9035年,汪星精锐舰队聚集在近喵星轨道,企图一举拿下喵星。大部分喵星人已经被转移到防空工事中。喵星国王下令出动最强战力迎击来敌。喵小c是战斗机编队到王牌飞行员,参加了上百场战斗,获得了很多荣誉,他是本次先头部队的一员。 
       “装载初级武器,装载初级防御罩,装载初级逃生仓。准备完毕,出发!”,航空港的扩音机发出急促的声音。伴随着引擎的轰鸣,战斗机编队已经离开跑道,朝汪星舰队飞去。下面是当前的源代码:

这个是战斗机的代码,喵小c就坐在飞机里,所以代码就省了。

/**
 * 战斗机
 * @author bob
 *
 */
public class Battleplane {
    /**
     * 初级逃生舱
     */
    private PrimaryEscapeCompartment primaryEscapeCompartment;
    
    /**
     * 初级防御罩
     */
    private PrimaryShield primaryShield;
    
    /**
     * 初级武器
     */
    private PrimaryWeapon primaryWeapon;

    public PrimaryEscapeCompartment getPrimaryEscapeCompartment() {
        return primaryEscapeCompartment;
    }

    public void setPrimaryEscapeCompartment(PrimaryEscapeCompartment primaryEscapeCompartment) {
        this.primaryEscapeCompartment = primaryEscapeCompartment;
    }

    public PrimaryShield getPrimaryShield() {
        return primaryShield;
    }

    public void setPrimaryShield(PrimaryShield primaryShield) {
        this.primaryShield = primaryShield;
    }

    public PrimaryWeapon getPrimaryWeapon() {
        return primaryWeapon;
    }

    public void setPrimaryWeapon(PrimaryWeapon primaryWeapon) {
        this.primaryWeapon = primaryWeapon;
    }
    
}
 

下面是战斗机需要装备的设备

/**
 * 初级逃生舱
 * 
 * @author bob
 *
 */
public class PrimaryEscapeCompartment {

    public String description() {
        return "逃生能力一般";
    }
}

/**
 * 初级防护罩
 * 
 * @author bob
 *
 */
public class PrimaryShield {

    public String protect(){
        return "防御了一次攻击,但是防御罩受损";
    }
}

/**
 * 初级武器
 * @author bob
 *
 */
public class PrimaryWeapon {
    
    public String shoot(){
        return "突突突";
    }
    
}
 

下面是战斗机起飞的机场

 package com.bob.designpatterns.abstractfactory.stepone;

/**
 * 机场
 * @author bob
 *
 */
public class Airport {
    
    public static void main(String[] args) {
        //起飞前的准备
        Battleplane battleplane = new Battleplane();
        prepareToFly(battleplane);
        
        //起飞
    }
    
    /**
     * 战斗机起飞前的准备工作
     * @param battleplane
     */
    public static void prepareToFly(Battleplane battleplane){
        battleplane.setPrimaryEscapeCompartment(new PrimaryEscapeCompartment());
        battleplane.setPrimaryShield(new PrimaryShield());
        battleplane.setPrimaryWeapon(new PrimaryWeapon());
    }
    

}
 

       像大部分的剧情一样,喵星的首轮自卫反击战以失败落幕,喵小c顶着主角光环成功飞回。
       “中级战斗装备研制完成,马上装备到战斗机上了”,战斗后勤部得到了上级通知,同时愁上心头….WHY?

2.存在的问题

       请看Airport类中prepareToFly中负责产生战斗装备(直接new了),紧密得耦合在一起。另外请看Battleplane类中也与初级的装备耦合严重。除了耦合问题以外战斗装备分为多个部分,替换的时候容易漏替,要知道初级战斗装备和中级战斗装备之间不能混搭,一旦搭错将会出现不兼容的情况,给战斗机带来额外风险。所以要解决两个问题:1.保证灵活得升级现有装备 2.要按照级别统一升级,不能有部分升级的情况。

3.抽象工厂模式登场

       抽象工厂模式的意图:提供一个创建一系列相关或者相互依赖的对象的接口,而无需指定他们具体的类。 听起来略微有些抽象,我们继续讲故事。

       让我们将时间回退到1年前的喵星。改变历史,解决1年后的困境。我门重新设计一下:

经过酝酿,新的设计出现了:设计模式演练——抽象工厂模式第1张抽象工厂模式常见的实现方式是使用工厂方法模式实现,也可以使用原型模式实现。本文中的实现方式为前者。关于原型模式的实现方式,下一篇写完原型模式后会补充上来。

下面只给出Airport部分代码,完整代码在https://github.com/mingbozhang/designpattern

package com.bob.designpatterns.abstractfactory.steptwo;

/**
 * 机场
 * 
 * @author bob
 *
 */
public class Airport {

    /**
     * 战斗准备系统
     */
    private static FightPrepareSys fightPrepareSys;

    public static void setFightPrepareSys(FightPrepareSys fightPrepareSys) {
        Airport.fightPrepareSys = fightPrepareSys;
    }

    public static void main(String[] args) {
        // 设置初级战斗准备系统
        // Airport.setFightPrepareSys(new PrimaryFightPrepareSys());
        // 设置中级战斗准备系统
        Airport.setFightPrepareSys(new MidFightPrepareSys());

        // 起飞前的准备
        Battleplane battleplane = new Battleplane();
        prepareToFly(battleplane);

        // 起飞
    }

    /**
     * 战斗机起飞前的准备工作
     * 
     * @param battleplane
     */
    public static void prepareToFly(Battleplane battleplane) {
        battleplane.setEscapeCompartment(fightPrepareSys.getEscapeCompartment());
        battleplane.setShield(fightPrepareSys.getShield());
        battleplane.setWeapon(fightPrepareSys.getWeapon());
    }

}

4.解决了什么,失去了什么

       引入抽象工厂后,对于多个系列的产品(对应故事中战斗装备各系列)更容易管理,限制取得产品与同系列产品版本风格保持一致。使创建产品与使用者解藕,根据抽象类进行交互。 
       如果想要新增加一个产品的创建,且同时保证使用者的简洁实用,则比较困难。

5.具体应用场景

       如果一个系统需要对应多个系列的产品则可以使用抽象工厂模式。举个《设计模式》书中的例子:当制作一款编辑器界面包含多种风格,界面元素包括各个控件,如:按钮、滚动条等。可以创建一个抽象的WidgetFactory包含创建各种控件的抽象方法。具体风格再实现Style1WidgetFactory、Style2WidgetFactory,生产各自风格系列的具体控件。这样就达到风格可以灵活扩展,且切换风格的时候非常简单,整个系统中只有在初始化具体工厂的时候需要改动。

6.参考

《设计模式-可复用面向对象软件的基础》

免责声明:文章转载自《设计模式演练——抽象工厂模式》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇JPA,EclipseLink 缓存机制学习——树节点搜索问题引发的思考java归并排序,单线程vs多线程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[Python设计模式] 第15章 如何兼容各种DB——抽象工厂模式

github地址:https://github.com/cheesezh/python_design_patterns 题目 如何让一个程序,可以灵活替换数据库? 基础版本 class User(): """ 用户类,模拟用户表,假设只有ID和name两个字段 """ def __init__(self): s...

c++模板实现抽象工厂

类似于rime的rime::Class<factory type, product type>实现方式。 C++模板实现的通用工厂方法模式 1.工厂方法(FactoryMethod)模式 工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂...

23设计模式(3):Abstract Factory模式

定义:要创建一组相关或依赖对象提供一个接口,而你并不需要指定其具体类别。 类型:创建一个类模型 类图: 抽象工厂模式与工厂方法模式的差别 抽象工厂模式是工厂方法模式的升级版本号,他用来创建一组相关或者相互依赖的对象。他与工厂方法模式的差别就在于。工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则是针对的多个产品等级结构。在编程中。通常一个...

设计模式系列命令模式

一、开篇 上一篇我们讲述了结构型模式中的代理模式。本篇,我们将会开始讲述行为型模式中的命令模式,在设计模式的这些基本的模式完成后,我将会将一 些经常用的其他的一些扩展的模式进行讲解,希望能够引起大家的共鸣。 我们先来看看命令模式的定义吧: 命令模式是将一类对象的功能操作进行抽象,一般来说,这些对象有相同的方法,所以这类对象有着类似的...

设计模式简单工厂、工厂方法、抽象工厂方法

定义: 工厂方法:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个.工厂方法让类把实例化推迟到子类 抽象工厂模式:提供一个接口,用于创建相关或依赖具体对象的家族,而不需要明确指定具体类. 要点: 所有的工厂都是用来封装对象的创建 简单工厂,虽然不是真正的设计模式,但仍不失位一个简单的办法,可以将客户程序从具体类中解耦出来 工厂方法使用...

设计模式-抽象工厂模式(AbstractFactory)(创建型模式)

//以下代码来源: 设计模式精解-GoF 23种设计模式解析附C++实现源码 //Product.h #pragma once classAbstractProductA { public: virtual ~AbstractProductA(); protected: AbstractProductA(); private: }; c...