• 23种设计模式[3]:抽象工厂模式


    一、简单工厂模式(静态工厂方法,不属于23种GOF设计模式之一)

    定义:定义一个用于创建产品对象的方法,由该工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

    类型:创建类模式

    public interface SmsService {
        void sendSms();
    }
    
    public class MontnetsSmsService implements SmsService {
        @Override
        public void sendSms() {
            System.out.println("通过梦网发送!");
        }
    }
    
    public class EtonenetSmsService implements SmsService {
        @Override
        public void sendSms() {
            System.out.println("通过移通发送!");
        }
    }
    
    public class SmsServiceFactory {
    
        public static SmsService getSmsService(int providerId) {
            SmsService ss;
    
            switch (providerId) {
                case 0:
                    ss = new MontnetsSmsService();
                    break;
                case 1:
                    ss = new EtonenetSmsService();
                    break;
                default:
                    ss = new EtonenetSmsService();
            }
    
            return ss;
        }
    
        public static void main(String[] args) {
            SmsService ss = SmsServiceFactory.getSmsService(0);
            //发送短信
            ss.sendSms();
        }
    }

    二、工厂方法模式

    定义:定义一个用于创建产品对象的接口,由子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。

    类型:创建类模式

    类图:

    工厂方法模式代码:

    public interface SmsService {
        void sendSms();
    }
    
    //工厂接口
    public interface SmsServiceFactory {
        SmsService getSmsService(int providerId);
    }
    
    public class MontnetsSmsService implements SmsService {
        @Override
        public void sendSms() {
            System.out.println("通过梦网发送!");
        }
    }
    
    public class EtonenetSmsService implements SmsService {
        @Override
        public void sendSms() {
            System.out.println("通过移通发送!");
        }
    }
    
    /**
     * 工厂实现类
     */
    public class SmsServiceFactoryImpl implements SmsServiceFactory{
    
        @Override
        public SmsService getSmsService(int providerId) {
            SmsService ss;
    
            switch (providerId) {
                case 0:
                    ss = new MontnetsSmsService();
                    break;
                case 1:
                    ss = new EtonenetSmsService();
                    break;
                default:
                    ss = new EtonenetSmsService();
            }
    
            return ss;
        }
    
        public static void main(String[] args) {
         //向上转型为工程接口
            SmsServiceFactory ssf = new SmsServiceFactoryImpl();
            SmsService ss = ssf.getSmsService(0);
            //发送短信
            ss.sendSms();
        }
    }

    工厂方法模式:

      通过工厂方法模式的类图可以看到,工厂方法模式有四个要素:

    • 工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来作为与调用者交互的接口,其本质上是一样的。
    • 工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。
    • 产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
    • 产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。

      上文提到的简单工厂模式跟工厂方法模式极为相似,区别是:简单工厂只有三个要素,他没有工厂接口,并且得到产品的方法一般是静态的(红色注释部分)。因为没有工厂接口,所以在工厂实现的扩展性方面稍弱,可以算所工厂方法模式的简化版。

    三、抽象工厂模式

    定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定他们的具体类。

    类型:创建类模式

    类图:

    抽象工厂模式代码:

    public interface SmsService {
        void sendMsg();
    }
    
    public interface NoticeService {
        void sendMsg();
    }
    
    public interface MsgServiceFactory {
        SmsService getSmsService();
        
        SmsService getNoticeService();
    }
    
    public class MontnetsSmsService implements SmsService {
        @Override
        public void sendSms() {
            System.out.println("通过梦网发送!");
        }
    }
    
    public class EtonenetSmsService implements SmsService {
        @Override
        public void sendMsg() {
            System.out.println("通过移通发送!");
        }
    }
    
    public class ApnsService implements NoticeService {
        @Override
        public void sendMsg() {
            System.out.println("通过APNS发送!");
        }
    }
    
    public class JpushService implements NoticeService {
        @Override
        public void sendMsg() {
            System.out.println("通过极光发送!");
        }
    }
    
    /**
     * 抽象工厂实现类1
     */
    public class MsgServiceFactoryImpl implements MsgServiceFactory{
    
        @Override
        public SmsService getSmsService() {
            return new MontnetsSmsService();
        }
        
        @Override
        public NoticeService getNoticeService() {
            return new ApnsService();
        }
        
        public static void main(String[] args) {
         //向上转型为工程接口
            SmsServiceFactory ssf = new SmsServiceFactoryImpl();
            //发送消息通过短信,移通
            ssf.getSmsService().sendMsg();
            //发送消息通过App,APNS
            ssf.getNoticeService().sendMsg();
        }
    }
    
    /**
     * 抽象工厂实现类2
     */
    public class MsgServiceFactoryImpl implements MsgServiceFactory{
    
        @Override
        public SmsService getSmsService() {
            return new EtonenetSmsService();
        }
        
        @Override
        public NoticeService getNoticeService() {
            return new JpushService();
        }
        
        public static void main(String[] args) {
         //向上转型为工程接口
            MsgServiceFactory ssf = new MsgServiceFactoryImpl();
            //发送消息通过短信
            ssf.getSmsService().sendMsg();
            //发送消息通过App
            ssf.getNoticeService().sendMsg();
        }
    }

      抽象工厂模式是工厂方法模式的升级版本,抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。所谓的产品族,一般或多或少的都存在一定的关联,抽象工厂模式就可以在类内部对产品族的关联关系进行定义和描述,而不必专门引入一个新的类来进行管理。

      在抽象工厂模式中,有一个产品族的概念:所谓的产品族,是指位于不同产品等级结构中功能相关联的产品组成的家族。抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。

      如上代码中,产品族有短信、App通知。我们要实现消息的下发,可以通过如下两大产品类达到消息下发的目的。实际开发中的代码比如上编写的更紧凑,会结合简单工厂、工厂方法、抽象工厂、反射等编写。

     代码类似如下:

    public interface SmsService {
        void sendMsg();
    }
    
    public interface NoticeService {
        void sendMsg();
    }
    
    public interface MsgServiceFactory {
        SmsService getSmsService();
    
        SmsService getSmsService(int providerId);
        
        SmsService getSmsService(String className);
        
        SmsService getNoticeService();
        
        SmsService getNoticeService(int providerId);
        
        SmsService getNoticeService(String className);
    }
    
    public class MontnetsSmsService implements SmsService {
        @Override
        public void sendSms() {
            System.out.println("通过梦网发送!");
        }
    }
    
    public class EtonenetSmsService implements SmsService {
        @Override
        public void sendMsg() {
            System.out.println("通过移通发送!");
        }
    }
    
    public class ApnsService implements NoticeService {
        @Override
        public void sendMsg() {
            System.out.println("通过APNS发送!");
        }
    }
    
    public class JpushService implements NoticeService {
        @Override
        public void sendMsg() {
            System.out.println("通过极光发送!");
        }
    }
    
    /**
     * 抽象工厂实现类
     */
    public class MsgServiceFactoryImpl implements MsgServiceFactory{
    
        @Override
        public SmsService getSmsService() {
            return new EtonenetSmsService(); 
        }
    
        @Override
        public SmsService getSmsService(int providerId) {
            SmsService ss;
            switch (providerId) {
                case 0:
                    ss = new MontnetsSmsService();
                    break;
                case 1:
                    ss = new EtonenetSmsService();
                    break;
                default:
                    ss = new EtonenetSmsService();
            }
    
            return ss;
        }
        
        @Override
        public SmsService getSmsService(String className) {
            //使用反射
            Class clazz = Class.forName(className);
            return (SmsService) clazz.newInstance(); 
        }
        
        @Override
        public SmsService getNoticeService() {
            return new ApnsService(); 
        }
        
        @Override
        public NoticeService getNoticeService(int providerId) {
            NoticeService ns;
            switch (providerId) {
                case 0:
                    ns = new JpushService();
                    break;
                case 1:
                    ns = new ApnsService();
                    break;
                default:
                    ns = new ApnsService();
            }
    
            return ns;
        }
        
        @Override
        public NoticeService getNoticeService(String className) {
            //使用反射
            Class clazz = Class.forName(className);
            return (NoticeService) clazz.newInstance(); 
        }
        
        public static void main(String[] args) {
         //向上转型为工程接口
            SmsServiceFactory ssf = new SmsServiceFactoryImpl();
            //发送消息通过短信,移通
            ssf.getSmsService(0).sendMsg();
            //发送消息通过App,APNS
            ssf.getNoticeService(1).sendMsg();
        }
    }

    四、总结

      无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。

      所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了,不需要完全遵守各种模式的特点和约束来实现业务代码。

    如写的不好,欢迎拍砖!

    PS:

    http://blog.csdn.net/zhengzhb/article/details/7359385

  • 相关阅读:
    测试面试题集锦(一)| 软件测试常见必考问题与流程篇(附答案)
    测试开发赏金内推 | BAT 最新高薪急聘岗位,名企测试负责人等你来面!
    Xbox分辨率突然变成640p
    UWP 自定义密码框控件
    前端笔记(Antd将组件设置国际化中文)
    【数据结构与算法】背包问题总结梳理
    Redis网络模型的源码分析
    [MOOC-Java]1.2.1用变量做计算
    [MOOC-Java]1.1.2第一个程序
    [MOOC-Java]1.1.1开发环境配置
  • 原文地址:https://www.cnblogs.com/phpdragon/p/8302710.html
Copyright © 2020-2023  润新知