设计模式之工厂模式【选用修仙小说功法阐述】

       一生猿,一世猿。
                    —— 猿医生·yys 

                                                                 

一、前言

       工厂模式可分为 简单工厂模式、工厂方法模式、抽象工厂模式。

       工厂模式主要目的:封装创建过程逻辑,只对结果负责

       为解决猿友阅读时所产生的身心倦怠,在此,我会将 代码案例选为 番茄修仙小说《星辰变》中的功法秘籍选择

       望缓解各位猿友的专注力,小生却以努力了...  请不要吝啬您的赞,点个赞吧 ~

       在此记录下,分享给大家。

 

 二、简单工厂模式 

 

      简单工厂模式,又叫做静态工厂方法 (StaticFactory Method) 模式,是指由一个工厂对象决定创建出哪一种产品类的实例,但

它不属于 GOF 23 种设计模式。简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如

何创建对象的逻辑不需要关心。

 

      接下来看代码案例,我们以前言中提到的 “番茄写作的修仙小说《星辰变》为例 ”,是否看过不重要,重要的是保持专注的看

下去,层层递进理解三种工厂模式的关联以及演变,步入正题,小说主角“秦羽”,我们称之为“小羽”。

 

      小羽天生无法修炼内功。为了得到父亲的重视关注,他毅然选择了修炼痛苦艰难的外功,经过不懈的努力,终于达到了 先天 

大圆满境界,此时面临着功法选择的问题,摆在眼前的有两种功法可选,一种不完善残缺的《星辰变功法》却也是最适合自己的

的功法,另一种是常人普遍修炼的功法《普通修仙功法》,选择权在大家手中哦...

             

      接下来,我们可以定义一个 修仙功法标准的  IMartialArts 接口:

/**
 * 功法秘籍
 *      Interface
 * @author yys
 */
public interface IMartialArts {

    /**
     * 修炼功法
     */
    void practice();

}

      创建普通修仙功法  NormalArts 实现类:

/**
 * 普通修仙功法
 * @author yys
 */
public class NormalArts implements IMartialArts {

    public void practice() {
        System.out.println("金丹期->元婴期->洞虚期->空冥期->渡劫期->大成期->天仙期->金仙期->玄仙期->神人期->天尊,注定不凡。");
    }

}

      创建星辰变功法功法  XingChenBianArts 实现类:

/**
 * 星辰变功法
 * @author yys
 */
public class XingChenBianArts implements IMartialArts {

    public void practice() {
        System.out.println("星云->流星->星核->行星->渡劫->恒星->暗星->黑洞->原点->乾坤之境->宇宙,唯我独尊。");
    }

}

      创建 MartialArtsFactory 功法秘籍简单工厂 :

/**
 * 功法秘籍简单工厂
 * @author yys
 */
public class MartialArtsFactory {

    public static IMartialArts create(Class<? extends IMartialArts> clazz) {
        if(null != clazz) {
            try {
                return clazz.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}

      简单工厂模式 - 测试类及测试结果:

/**
 * 简单(静态)工厂模式
 *      Test
 * @author yys
 */
public class SimpleFactoryTest {

    /*
     * 缺点:
     *      1、工厂类的职责相对过重,不易于扩展过于复杂的产品结构
     *
     * 应用场景:
     *      1、适用于工厂类负责创建的对象较少的场景
     */
    public static void main(String[] args) {

        MartialArtsFactory artsFactory = new MartialArtsFactory();
        IMartialArts iMartialArts = artsFactory.create(XingChenBianArts.class);
//        IMartialArts iMartialArts = artsFactory.create(NormalArts.class);
        iMartialArts.practice();
    }

}

 

                   

 

      简单工厂模式总结:

            1、由工厂决定实例化哪种产品类的实例

            2、适用于工厂类负责创建的对象较少的场景

      缺点:

            1、工厂类的职责过重

 

      这时会发现简单工厂模式的一个弊端,工厂类的职责过重(有点类似万能工厂),且需要客户端传递参数,套用本文代码

案例来说,每一种修仙功法修炼达到极致的修仙者们,必定是穷极一生去修炼去参悟,而不会兼修别的修仙功法,可想而知

结果必定走火入魔,而每一种修仙功法对应的修仙者们自然而然分成不同的功法派系,小羽在普通修仙功法派系必然不会寻

得星辰变功法,反之亦然。这样,小羽想要修炼什么修仙功法,则去哪个功法派系(工厂)去寻得。而对应工厂模式也一样,

根据单一职责我们将职能继续拆分,专人做专事,我们将由工厂决定创建哪个类的实例,改为由工厂接口的实现类来决定实

例化哪个类,通俗一点:让类的实例化延迟到子类中执行(子类对应某个功法派系),就这样....演变出了 工厂方法模式 ... 

      哈哈,觉得像那么回事,能感觉到作者确实付出努力的各位博友们,点个免费的赞吧,动动小手吧~

 

 

 三、工厂方法模式

 

      工厂方法模式 是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子

类中进行。在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。

 

      接下来,我们定义一个 修仙功法的  IMartialArtsFactory 顶层工厂接口: 

/**
 * 功法秘籍顶层工厂
 * @author yys
 */
public interface IMartialArtsFactory {

    IMartialArts create();

}

      创建 NormalArtsFactory 普通修仙功法工厂 :

/**
 * 功法秘籍-普通修仙功法工厂
 * @author yys
 */
public class NormalArtsFactory implements IMartialArtsFactory {

    public IMartialArts create() {
        return new NormalArts();
    }

}

      创建 XingChenBianArtsFactory 星辰变功法工厂 :

/**
 * 功法秘籍-星辰变功法工厂
 * @author yys
 */
public class XingChenBianArtsFactory implements IMartialArtsFactory {

    public IMartialArts create() {
        return new XingChenBianArts();
    }

}

      简单工厂模式 - 测试类及测试结果:

/**
 * 工厂方法模式
 *      Test
 * @author yys
 */
public class FactoryMethodTest {

    /*
     * 缺点:
     *      1、类的个数容易过多,增加复杂度
     *      2、增加了系统的抽象性和理解难度
     *
     * 应用场景:
     *      1、创建对象需要大量重复的代码
     *      2、客户端(应用层)不依赖于产品类实例如何被创建、实现等细节
     *      3、一个类通过其子类来指定创建哪个对象
     */
    public static void main(String[] args) {

//        // 星辰变功法工厂
//        IMartialArtsFactory factory = new XingChenBianArtsFactory();
//        IMartialArts martialArts = factory.create();
//        martialArts.practice();


        // 普通修仙功法工厂
        IMartialArtsFactory factory = new NormalArtsFactory();
        IMartialArts martialArts = factory.create();
        martialArts.practice();

    }

}

 

      

 

      工厂方法模式总结:

            1、由工厂接口的实现类来决定实例化哪个类,让类的实例化延迟到子类中执行

            2、只限于同一产品等级结构的产品 (产品等级结构概念在抽象工厂模式中会讲解)

      缺点:

            1、在增加新的产品时,也必须增加新的工厂类,工厂方法的工厂个数过多,会带来额外的开销​​​​​​

 

      我们继续说,再将来某天,如果产品升级需要增加一个产品类 (eg:其他修仙功法),我们并不需要修改任何的源代码,

只需再创建一个其他修仙功法工厂并实现顶层工厂即可,乍一看我们发现,工厂方法模式似乎很完美 (nice),其实不然,大

家仔细观察工厂方法模式就会发现,如果我们实现的产品接口有多个,不同的产品接口有对应的产品族(产品族概念在抽象

工厂模式中会讲解),针对这种情况我们可以采用抽象工厂模式

 

 

 四、抽象工厂模式

 

      抽象工厂模式 是指提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类。客户端(应用层)不依赖于产

品类实例如何被创建、实现等细节,强调的是一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量重复的代码。

需要提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。

 

再上述工厂方法模式总结提到 :产品族、产品等级结构两个概念,下面来简单阐述下:

 

                    

图画的不好,莫见怪哈 ~

从图中可以看到矩形和圆形两种图形,相同颜色的就代表一个产品族,相同形状的代表一个产品等级结构。

结合代码案列来说,上图中黄色矩形代表 “修炼” 星辰变功法,黄色圆形代表 “完善创造”星辰变功法,黄色的一排都属于星辰变功

法,都是星辰变功法这个产品族。再看右侧的圆形,黄色圆形代表 “完善创造”星辰变功法,粉红色圆形代表 “完善创造”普通修仙功法,都是 “完善创造” 功法,这都属于同一个产品等级结构。

 

                 

如图所示,最左侧的房子图案代表我们具体的工厂,结合代码案例,有星辰变功法工厂,普通修仙功法工厂,而每个功法工厂都可以 “修炼功法”、“完善创造功法”。

 

      这样,我们产品等级结构中需定义两个产品接口,完善创建功法 IArtsCreate 接口、修炼功法 IArtsPractice 接口:

/**
 * 完善/创造功法
 * @author yys
 */
public interface IArtsCreate {

    /**
     * 功法完善
     */
    void improve();

}
/**
 * 修炼功法
 * @author yys
 */
public interface IArtsPractice {

    /**
     * 打坐修炼
     */
    void practice();

}

 

      创建 IMartialArtsFactory 功法秘籍抽象工厂 :

/**
 * 功法秘籍抽象工厂
 *  抽象工厂是用户的主入口,在Spring中应用得最为广泛的一种设计模式,易于扩展
 * @author yys
 */
public abstract class IMartialArtsFactory {

    // 创建 功法完善
    abstract IArtsImprove createArtsImprove();

    // 创建 修炼功法
    abstract IArtsPractice createArtsPractice();

}

 

      接下来 创建 星辰变功法产品族相关产品及工厂:

            产品等级一:星辰变功法 “修炼功法”类:

/**
 * 星辰变功法 - 修炼
 * @author yys
 */
public class XingChenBianArtsPractice implements IArtsPractice {

    public void practice() {
        System.out.println("星云->流星->星核->行星->渡劫->恒星->暗星->黑洞->原点->乾坤之境->宇宙,唯我独尊。");
    }

}

            产品等级二:星辰变功法 “完善创造功法”类:

/**
 * 星辰变功法 - 完善/创造
 * @author yys
 */
public class XingChenBianArtsImprove implements IArtsImprove {

    public void improve() {
        System.out.println("星辰变功法乃未完成功法,那么...就由我继续创造。。问鼎宇宙。");
    }

}

             星辰变功法  XingChenBianArtsFactory 具体工厂:

/**
 * 星辰变功法工厂
 * @author yys
 */
public class XingChenBianArtsFactory extends IMartialArtsFactory {

    public IArtsImprove createArtsImprove() {
        return new XingChenBianArtsImprove();
    }

    public IArtsPractice createArtsPractice() {
        return new XingChenBianArtsPractice();
    }
}

 

      接下来 创建 普通修仙功法产品族相关产品及工厂:

            产品等级一:普通修仙功法 “修炼功法”类:

/**
 * 普通修仙功法 - 修炼
 * @author yys
 */
public class NormalArtsPractice implements IArtsPractice {

    public void practice() {
        System.out.println("金丹期->元婴期->洞虚期->空冥期->渡劫期->大成期->天仙期->金仙期->玄仙期->神人期->天尊,注定不凡。");
    }

}

            产品等级二:普通修仙功法 “完善创造功法”类:

/**
 * 普通修仙功法 - 完善/创造
 * @author yys
 */
public class NormalArtsImprove implements IArtsImprove {

    public void improve() {
        System.out.println("普通修仙功法完善....");
    }

}

             普通修仙功法  NormalArtsFactory 具体工厂:

/**
 * 普通修仙功法工厂
 * @author yys
 */
public class NormalArtsFactory extends IMartialArtsFactory {

    public IArtsImprove createArtsImprove() {
        return new NormalArtsImprove();
    }

    public IArtsPractice createArtsPractice() {
        return new NormalArtsPractice();
    }
}

 

      抽象工厂模式 - 测试类及测试结果:

/**
 * 抽象工厂模式
 *      Test
 * @author yys
 */
public class AbstractFactoryTest {

    /*
     * 缺点:
     *      1、规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂的接口
     *      2、增加了系统的抽象性和理解难度
     */
    public static void main(String[] args) {

//        // 普通修仙功法
//        IMartialArtsFactory factory = new NormalArtsFactory();
//        IArtsPractice artsPractice = factory.createArtsPractice();
//        artsPractice.practice();
//        IArtsImprove artsImprove = factory.createArtsImprove();
//        artsImprove.improve();

        // 星辰变功法
        IMartialArtsFactory factory = new XingChenBianArtsFactory();
        IArtsPractice artsPractice = factory.createArtsPractice();
        artsPractice.practice(); // 修炼功法
        IArtsImprove artsImprove = factory.createArtsImprove();
        artsImprove.improve(); // 完善创造功法

    }

}

 

           

 

      抽象工厂模式总结:

            1、提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类

                  (相关或相互依赖:不同产品等级结构中功能相关联的产品组成的家族)

            2、工厂方法模式升级版,针对于多种产品等级结构的产品 

      缺点:

            1、增加产品族扩展简单,而增加产品等级结构扩展困难 (需修改抽象工厂,不符合开闭原则)

 

      抽象工厂模式缺点中提到 “增加产品族扩展简单,而增加产品等级结构扩展困难 ”,我们结合代码案例来说:

比如我们增加一个 “其他修仙功法” 产品族 我们只需增加对应的工厂,以及每个产品增加 其他修仙功法对应的修炼功法、完善功法的方法即可,完全符合 “开闭原则”。

如果增加一个 “传授功法”的产品等级,就需要增加 传授功法 接口,星辰变传授功法类,普通修仙功法传授功法类,同时还需要修改功法秘籍抽象工厂,星辰变功法工厂,普通修仙功法工厂,麻烦且违背了开闭原则。

所以,世上并无绝对完美的东西,何时需思其用。

 

      友情提示 - 个人总结 - 抽象工厂定义及创建顺序

            1、确定产品族和产品等级;

            2、定义产品等级对应产品接口,一个产品等级对应一个接口;

            3、定义抽象工厂,一般为产品族的总标准(eg:大众汽车产品族 / 尼桑汽车产品族,抽象工厂为 :汽车抽象工厂);

            4、定义产品族相关产品类及具体工厂;

 

 

 五、三种工厂模式对比总结

 

      简单工厂模式 (Simple Factory Pattern),又叫静态工厂模式 (StaticFactory Method):

            1、一个 工厂 来决定创建哪一种产品类的实例,工厂方法为静态方法,它不属于 GOF 23 种设计模式;

            2、只适用于工厂类负责创建的对象较少的场景;

            3、工厂类的职责过重且需要传递参数,违反单一职责原则,故需升级为 工厂方法模式。

 

      工厂方法模式(Factory Method Pattern)

            1、由工厂接口的实现类来决定实例化哪个类,让类的实例化延迟到子类中执行;

            2、只限于同一产品等级结构的产品 ,故需升级为 抽象工厂模式。

 

      抽象工厂模式(Factory Method Pattern)

            1、提供一个创建一系列相关或相互依赖对象的接口,无须指定他们具体的类;

            2、定义抽象(abstract)工厂,一个产品等级定义一个产品接口;

            3、工厂方法模式升级版,针对于多种产品等级结构的产品 。

 

      此工厂模式博文写到这里就结束了,很感谢各位博友的阅读,相信或多或少可以为您答疑解惑。

      最后,还是一样 ~ 哈哈,各位博友辛苦下,点个免费的赞吧,动动小手吧 ~ 

      后续继续为大家更新设计模式相关博文。

 

 

                       Now ~ ~ ~写到这里,就写完了,如果有幸帮助到你,请记得关注我,共同一起见证我们的成长

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿医生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值