资讯专栏INFORMATION COLUMN

设计模式之工厂模式

huangjinnan / 3357人阅读

摘要:缺点需要慎重考虑是否增加工厂类进行管理,因为会增加代码的复杂度使用场景工厂模式是创建型模式的一种,其实就等价于对象,但是否将对象改造成工厂模式,使我们需要衡量的。

前言

最近北京天气越来越冷了,同在北京的小伙伴大家注意保暖。不扯废话了,让我们直接进入到工厂模式的学习.

什么是工厂模式
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。
UML类图 (lol版)

工厂模式的优缺点

优点:良好的封装性,代码结构清晰,扩展性非常强。屏蔽产品类,产品的实际创建在工厂类中,产品类的实现如何变化,调用者都不需要关心,只要关心产品的接口即可。

缺点:需要慎重考虑是否增加工厂类进行管理,因为会增加代码的复杂度

使用场景

工厂模式是创建型模式的一种,其实就等价于new对象,但是否将new对象改造成工厂模式,使我们需要衡量的。工厂模式是一个非常灵活的框架设计,比如我们使用的jdbc,数据库分为oracle和mysql,这些都是产品类,若我们新增一种数据库,只需要增加其产品类就行,符合开闭原则。

代码分析
//所有英雄的父类
public abstract class Hero {

    public void fromGame() {
        System.out.println("i am come from lol");
    }
    //英雄类型
    abstract void typeOf();
    //英雄特点
    abstract void feature();
}
public class Mage extends Hero {
    @Override
    void typeOf() {
        System.out.println("我是法师");
    }

    @Override
    void feature() {
        System.out.println("我的法术伤害很爆炸");
    }
}
public class Tank extends Hero {
    @Override
    void typeOf() {
        System.out.println("我是坦克");
    }

    @Override
    void feature() {
        System.out.println("我很肉,我抗性很高");
    }
}
public class Assassin extends Hero {
    @Override
    void typeOf() {
        System.out.println("我是刺客");
    }

    @Override
    void feature() {
        System.out.println("我瞬间伤害很爆炸");
    }
}

就先定义三种类型英雄,其他省略,毕竟我们是学设计模式不是打游戏的....

//抽象工厂,定义创建英雄方法
public abstract class AbstractFactory {

    abstract T createHero(Class clazz) throws ClassNotFoundException, IllegalAccessException, InstantiationException;
}
//工厂真正的实现类
public class Factory extends AbstractFactory {
    @Override
     T createHero(Class clazz) {
        Hero hero = null;
        try {
            hero = (Hero) Class.forName(clazz.getName()).newInstance();
        } catch (Exception e) {
            System.out.println("class文件有问题");
        }
        return (T) hero;
    }
}
//测试类
public class Client {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        AbstractFactory factory = new Factory();
        Hero hero = factory.createHero(Mage.class);
        Hero hero2 = factory.createHero(Assassin.class);
        Hero hero3 = factory.createHero(Tank.class);

        hero.fromGame();hero.typeOf();hero.feature();
        hero2.fromGame();hero2.typeOf();hero2.feature();
        hero3.fromGame();hero3.typeOf();hero3.feature();
    }
}
测试结果:
i am come from lol
我是法师
我的法术伤害很爆炸
i am come from lol
我是刺客
我瞬间伤害很爆炸
i am come from lol
我是坦克
我很肉,我抗性很高

这就是最常见的工厂模式,一定会有小伙伴说你少定义了adc和support。我们现在来思考一下,在这个基础框架上如何将adc和support加进去。其实我们只需要定义adc和support类,让其继承于hero,工厂类什么都不用改,测试类或高层模块就可以直接使用,是不是很流弊....

工厂模式的扩展

简单工厂模式

假如一个模块仅需要一个工厂类,基于这样的业务,我们根本没必要在测试类或高层模块中将工厂类给生产出来,使用其静态方法就好了。应该去除抽象工厂类,修改工厂实现类为静态方法即可.代码示例:

public class Factory  {
     static   T createHero(Class clazz) {
        Hero hero = null;
        try {
            hero = (Hero) Class.forName(clazz.getName()).newInstance();
        } catch (Exception e) {
            System.out.println("class文件有问题");
        }
        return (T) hero;
    }
}
public class Client {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Hero hero = Factory.createHero(Mage.class);
        Hero hero2 = Factory.createHero(Assassin.class);
        Hero hero3 = Factory.createHero(Tank.class);

        hero.fromGame();hero.typeOf();hero.feature();
        hero2.fromGame();hero2.typeOf();hero2.feature();
        hero3.fromGame();hero3.typeOf();hero3.feature();
    }
}

运行结果不会有任何变化,我们的uml类图也会变得简单,调用者也就是测试类或者项目中的高层模块调用起来也会简单,其缺点就是工厂类扩展比较麻烦,不符合开闭原则。

多个工厂类

原来的工厂负责所有类型英雄的创建,职责有点太多了。多个工厂类顾名思义就是对工厂类进行拆分,使其符合单一职责原则。当我们遇到一个非常复杂的项目时,产品类会有很多,并且在我们获得一个产品类很可能都需要对其初始化,不同的产品类会有不同的实现,假如都写在一个工厂类里,会出现很长很长的if/else或者swtich之类得判断语句,这种代码是有毒的!假如你的代码中有类似代码,就应该考虑下能不能给重构了.
UML图:

public abstract class AbstractFactory {

    abstract Hero createHero();
}
public class AssassianFactory extends AbstractFactory {

    @Override
    Hero createHero() {
        return new Assassin();
    }
}
public class TankFactory extends AbstractFactory {

    @Override
    Hero createHero() {
        return new Tank();
    }
}
public class MageFactory extends AbstractFactory {

    @Override
    Hero createHero() {
        return new Mage();
    }
}
public class Client {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
        Hero mageHero = new MageFactory().createHero();
        Hero tankHero = new TankFactory().createHero();
        Hero assassinHero = new AssassianFactory().createHero();
    }
}

每一个产品类都对应了一个工厂,好处就是职责清晰,结构简单。坏处就是我们扩展新的产品时,需要额外扩展一个工厂类,增加了扩展的难度

延迟初始化

一个对象被消费完毕后,并不立即释放,工厂类保持其初始化,等待再次被使用.
public class HeroFactory {
    private static final Map heroMap = new HashMap<>();

    public static synchronized Hero createHero(String type) {
        Hero hero = null;
        if (heroMap.containsKey(type)) {
            return heroMap.get(type);
        } else {
            if (type.equals("mage")) {
                hero = new Mage();
            } else if (type.equals("tank")) {
                hero = new Tank();
            } else {
                hero = new Assassin();
            }
            heroMap.put(type, hero);
        }
        return hero;
    }

}

我们定义了一个静态常量heroMap,在内存中对工厂创建的对象进行延迟化,方便下次调用。同时也非常方便扩展,比如我们在玩英雄联盟,知道双方英雄不会超过10个,可以根据map的长度,判断内存中最多的hero实例数。

总结

工厂模式是一个很常见很优秀的设计模式,我们应该多思考工厂方法如何应用,而且工厂模式和原型模式单例模式结合起来会用更多神奇的设计!不用着急,我们慢慢来...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70630.html

相关文章

  • PHP面试常考设计模式——工厂模式

    摘要:工厂模式其实可以划分为简单工厂模式工厂方法模式抽象工厂模式等。简单工厂模式介绍简单工厂模式又称为静态工厂方法模式,它属于类创建型模式。此模式是对工厂方法模式的进一步扩展。 你好,是我琉忆,PHP程序员面试笔试系列图书的作者。 本周(2019.3.11至3.15)的一三五更新的文章如下: 周一:PHP面试常考之设计模式——工厂模式周三:PHP面试常考之设计模式——建造者模式周五:PHP...

    Jiavan 评论0 收藏0
  • Spring框架我见(一)——工厂模式

    摘要:相对于工厂模式,抽象工厂模式生产的对象更加具体,也更加丰富,但相对编码也更加复杂。具体的抽象工厂模式的实现大家可以参考菜鸟教程。知道了工厂模式和抽象工厂模式的区别,请大家使用的时候应该根据具体的情况进行选择。 大家好,今天给大家分享一些Spring的学习心得,在讲Spring之前,先和大家分享Spring中核心的设计模式。 工厂模式 在聊概念之前我先问问大家:什么是工厂? 这个很简单,...

    venmos 评论0 收藏0
  • 优才公开课笔记:php设计模式 (二)工厂模式

    摘要:但本质是,简单工厂并未严格遵循设计模式的开闭原则,当需要增加新产品时也需要修改工厂代码。但是工厂方法则严格遵守开闭原则,模式只负责抽象工厂接口,具体工厂交给客户去扩展。 最近开展了三次设计模式的公开课,现在来总结一下设计模式在PHP中的应用,这是第二篇创建型模式之工厂模式。 设计模式的一般介绍在第一篇文章讲了,这里就不重复。 工厂模式 实现:定义一个用于创建对象的接口,让子类决定实...

    aisuhua 评论0 收藏0
  • 设计模式系列工厂模式

    摘要:设计模式之工厂模式工厂模式包括了简单工厂工厂方法和抽象工厂。工厂方法模式下面我们针对普通工厂模式的缺点进行优化。 设计模式之工厂模式 工厂模式包括了简单工厂、工厂方法和抽象工厂。下面我从java实际应用的角度分别介绍这三种模式。 简单工厂模式 下面看下JDBC中获取Connection的代码 public class ConnectionFactory { public Con...

    MrZONT 评论0 收藏0
  • 一天一个设计模式JS实现——工厂模式

    摘要:参考文章深入理解三种工厂模式工厂模式,工厂方法模式,抽象工厂模式详解工厂模式是中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 参考文章:深入理解java三种工厂模式工厂模式,工厂方法模式,抽象工厂模式 详解 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的...

    Muninn 评论0 收藏0
  • 工厂模式(一)抽象工厂模式

    摘要:主要详解简单工厂模式到抽象工厂模式的演变。抽象工厂模式当一个类别的产品还有多个系列区分时,为了按系列生产商品,使用抽象工厂区分。 主要详解简单工厂模式到抽象工厂模式的演变。 简单工厂模式 即静态工厂模式1.将对象的创建和使用分开;2.将生产过程集中,便于集中管理;3.当需要创建的对象类有变动时,就不用在所有new 的地方修改了,直接修改工厂类即可; /** * 简单工厂模式 ---...

    woshicixide 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<