V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
hakunamatata11
V2EX  ›  推广

工厂设计模式有什么用?

  •  
  •   hakunamatata11 · 2020-10-13 18:32:10 +08:00 · 1120 次点击
    这是一个创建于 1532 天前的主题,其中的信息可能已经有所发展或是发生改变。

    工厂方法是非常古老且常用的设计模式。原因主要是一个系统要运转起来一定会涉及到对象的实例化过程,如果对象的实例化分散在各种逻辑代码之间,那么就会非常零乱、难以维护,bug 自然也多。

    工厂方法的出现解决的就是对象创建的问题,把建立对象实例交给子类来进行。说白了,就是把建立对象实例的过程从正常的业务逻辑中剥离出去,通过抽象来实现。

    众所周知,设计模式是一个综合性使用的过程,如果单一地使用设计模式,往往会让你的代码显得繁杂且难以理解。同时设计模式也是大厂面试的常见问题,《大厂高频设计模式应用及分析》对设计模式高频考点有详细讲解。

    假设现在我们有这样一个 class,拥有底层的显示商城 Banner 的能力,这是之前我们用适配器模式建立的架构。

    public class Main{
        public static void main(String[] args){
            MobilePhoneBanner view = new MobilePhoneBanner();
            view.showBanner();
        }
    }
    

    可以看到外层调用仍然需要去感知什么样的设备应该实例化什么 Banner 的过程。现在我们用工厂方法改进这个架构,即解决调用方感知要实例化哪一种 Banner 对象的问题。

    这里我们用简单工厂模式就可以了,简单地说,就是把薄的那一层的能力抽象出来沉淀。

    首先用接口规约工厂类的能力,基本原则是同一个工厂实例化的类一般来说在同一个继承树上。

    public interface IBannerFactory{
        AbstractBannerScene createBannerMatchDevice(DeviceTYpe deviceType);
    }
    

    然后给我们要创建的子类增加一个父类

    public abstract class AbstractBannerScene{
        public abstract void showBanner();
    }
    
    public class MobilePhoneBanner extends AbstractBannerScene{
        private CreateBannerView createBannerView;
    
    public class PCBanner extends AbstractBannerScene{
        private CreateBannerView createBannerView
    

    实现工厂方法接口

    public class BannerFactory implements IBannerFactory{
        @Override
        public AbstractBannerScene createBannerMatchDevice(DeviceTYpe deviceType){
            if(deviceType == DeviceType.MOBILEPHONE){
                return new MobilePhoneBanner();
            }else{
                return new PCBanner();
            }
        }
    }
    

    改进后的调用

    public class Main {
        public static void main(String[] args) {
            IBannerFactory factory = null;
            try {
                factory = (IBannerFactory) Class.forName("designpattern.factory.BannerFactory").newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
              factory.createBannerMatchDevice(DeviceType.MOBILEPHONE).showBanner();
        }
    }
    

    总结下工厂方法模式架构

    这里 BannerFactory 被 IBannerFactory 进行接口规约,接口是架构的边界。

    使用工厂模式能给系统设计带来什么好处?

    1. 对于复杂参数构造的对象,可以很好的对外层屏蔽代码复杂性
    2. 很好的解耦能力,能将业务(上)层和基础计数层之间实现完全的解耦
    3. 可以控制运行上下文中实体对象的数量,降低内存使用量
    4. 屏蔽底层实现改动对上层的冲击

    使用工厂模式有什么缺陷?

    1. 一类产品需要对应一个具体的工厂,增加了代码的冗余度
    2. 工厂方法负责实例的创建,这个系统层次非常重要,一旦出问题,系统将不能正常工作
    3. 产品迭代时将迅速的增加工厂层的规模

    封装和继承是设计模式的“原料”,接口和抽象类的使用可以有效的改进我们的架构。

    设计模式在架构中要综合使用,同样的场景可以适配多种设计模式,但切记不要过度设计。

    工厂模式主要的意义:

    • 将实例化过程与业务逻辑真正的解耦
    • 屏蔽复杂的对象创建逻辑
    • 控制内存中存活对象的数量,防止 coredump 。

    以上内容我在《大厂高频设计模式应用及分析》中都有详细讲解,此外我会从零开始一个项目通过注入设计模式思想来迭代我们的架构,在不借助任何开源框架的基础上开始我们的编码。一次性搞定包括工厂方法、责任链模式、单例模式等在内的大厂设计模式高频考点。现在点击原价购买,然后在选择优惠框输入折扣码:58D382,即可 9 元获得全部课程!

    jones2000
        1
    jones2000  
       2020-10-14 00:58:28 +08:00
    少一个动态注册新的类到工厂类中,否在每次增加新的类都需要手动增加到 createBannerMatchDevice(), 耦合太大,不利于模块化。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2708 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:28 · PVG 08:28 · LAX 16:28 · JFK 19:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.