zoukankan      html  css  js  c++  java
  • 精通设计模式之工厂方法模式

    工厂方法模式

    工厂方法模式又被称为虚拟构造器(Virtual Constructor)

    作用

    定义用于创建对象的接口,但是让子类决定要实例化哪个类。工厂方法将类实例化推迟到子类。

    说明

    真实案例

    1. 铁匠制造武器。精灵需要精灵武器和兽人需要兽医武器。根据手头的客户,正确的类型的铁匠被召唤。
    2. 发送器发送信息。短信发送器发送短信息和邮件发送器发送邮件信息。根据业务需求,调用正确类型的发送器发送信息。

    简而言之

    工厂方法模式提供了一种将实例化逻辑委托给子类的方法

    维基百科定义

    在基于类的编程中,工厂方法模式是使用工厂方法来处理创建对象的问题的创建模式,而不必指定将要创建的对象的确切类。这可以通过调用工厂方法(在接口中指定并由子类实现)来实现,或者在基类中实现,并且可选地被派生类覆盖,而不是调用构造函数。

    程序示例

    以我们的信息发送器为例。首先我们有一个信息发送器接口和一些实现

    /**
     * Description: 定义发送者接口
     * <br /> Author: vimx86
     */
    public interface Sender {
    
        /**
         * 发送信息
         */
        void send();
    
    }
    
    /**
     * Description: 邮件发送者
     * <br /> Author: vimx86
     */
    public class MailSender implements Sender {
        @Override
        public void send() {
            System.out.println("邮件发送者发送了一封邮件!");
        }
    }
    
    /**
     * Description: 短信息发送者
     * <br /> Author: vimx86
     */
    public class SmsSender implements Sender {
        @Override
        public void send() {
            System.out.println("短信息发送者发送了一封邮件!");
        }
    }
    

    定义信息发送器生产工厂

    /**
     * Description: 发送工厂(普通工厂模式)
     * <br /> Author: vimx86
     */
    public class SimpleSendFactory {
    
        /**
         * 根据发送者类型名称生产对应发送者
         *
         * @param type 发送者类型
         * @return 具体发送者
         */
        public Sender produce(String type) {
            if ("mail".equals(type)) {
                return new MailSender();
            } else if ("sms".equals(type)) {
                return new SmsSender();
            } else {
                System.out.println("请输入正确的类型!");
                return null;
            }
        }
    
    }

    现在,根据发送器类型调用正确的信息发送器并发送信息。

    /**
     * Description: 测试普通工厂模式
     * <br /> Author: vimx86
     */
    public class SimpleSendFactoryTest {
        @Test
        public void test() throws Exception {
            SimpleSendFactory factory = new SimpleSendFactory();
            Sender sender = factory.produce("sms");
            sender.send();
        }
    }

    适用场景

    何时使用“工厂方法”模式

    • 一个类不能预期它必须创建的对象类
    • 一个类希望其子类来指定它创建的对象
    • 类将责任委托给几个辅助子类之一,并且您想要本地化哪个助手子类是委托的知识

    Known uses

    点进去看一看,理解一下 ^_^!!!
    * java.util.Calendar
    * java.util.ResourceBundle
    * java.text.NumberFormat
    * java.nio.charset.Charset
    * java.net.URLStreamHandlerFactory
    * java.util.EnumSet
    * javax.xml.bind.JAXBContext

    信息发送案例

    • 普通工厂模式
    • 多个工厂方法模式
    • 静态工厂方法模式

    工厂模式适合:凡是出现了大量的产品需要创建,并且具有共同的接口时,可以通过工厂方法模式进行创建。
    在以上的三种模式中,第一种如果传入的字符串有误,不能正确创建对象,
    第三种相对于第二种,不需要实例化工厂类,
    所以,大多数情况下,我们会选用第三种——静态工厂方法模式。

    工厂方法模式的运用

    结合实际业务进行分析运用设计案例

    业务场景

    获取不同票务商(大众,猫眼,蜘蛛等等)提供的影院实时座位图。
    考虑业务扩展,保证有新票务商的接入时不影响当前业务。提供扩展性,可维护性。

    分析设计

    因为每家票务商都需要提供实时座位图功能,故可抽象出共同的接口 实时座位图提供商 提供实时座位图功能。

    定义实时座位图提供商接口 RealTimeSeats 和实现具体票务商的子类。

    public interface RealTimeSeats{
        /**
        * 获取实时座位图信息
        */
        RealtimeSeatModel getSeats(RealTimeSeatsRequest realTimeSeatsRequest);
    }
    
    /**
     * Description: 猫眼获取实时座位图
     * <br /> Author: vimx86
     */
    public class MaoYanRealTimeSeats implements RealTimeSeats{
        @Override
        public RealtimeSeatModel getSeats(RealTimeSeatsRequest realTimeSeatsRequest) {
              // 猫眼获取实时座位图逻辑调用……
       }
    }
    
    /**
     * Description: 蜘蛛网获取实时座位图
     * <br /> Author: vimx86
     */
    public class SpiderRealTimeSeats implements RealTimeSeats{
        @Override
        public RealtimeSeatModel getSeats(RealTimeSeatsRequest realTimeSeatsRequest) {
            // 蜘蛛网获取实时座位图逻辑调用……
        }
    }
    

    定义获取实时座位图工厂

    
    /**
     * Description: 实时座位图工厂
     * <br /> Author: vimx86
     */
    public class RealTimeSeatsFactory {
    
        public static RealTimeSeats produceSpider() {
            return new SpiderRealTimeSeats ();
        }
    
        public static RealTimeSeats produceMaoYan() {
            return new MaoYanRealTimeSeats ();
        }
    
    }
    

    这种工厂方法模式 扩展需要修改工厂类,等我们学习了抽象工厂模式再进一步改进。

    参考资料

  • 相关阅读:
    Java 装箱、拆箱 包装器
    Oracle decode函数 除数为零
    Java并发编程之ConcurrentHashMap
    MessageDigest 类
    Java中关于OOM的场景及解决方法
    Memcached的一些知识
    Solr导入数据库数据
    前端学习笔记(zepto或jquery)——对li标签的相关操作(二)
    前端学习笔记(zepto或jquery)——对li标签的相关操作(一)
    DES加密深度优化——随机生成加密字符串
  • 原文地址:https://www.cnblogs.com/ljmatlight/p/9060791.html
Copyright © 2011-2022 走看看