zoukankan      html  css  js  c++  java
  • 一天一个设计模式:简单工厂模式

    存在的目的:

      解耦,在a类中如何想使用b类的某种功能,必须new 一个b对象出来,假如有一个c类,跟b实现了同一个接口,后续想要将b替换成c就需要更改在a中的代码,以此类推,代码的耦合度会随着项目复杂度越来越高,维护成本也会越来越高。

      使用简单工厂,使a类与工厂做耦合,然后工厂来提供接口的实现类即可,这样只需要对工厂进行维护就可以实现替换了成功解耦。

     

    核心思想:

      不在乎工厂是如何生产产品的,而是将产品的生产与产品的使用分开。
           注:这里的产品指的是功能类的对象

     

    实际的应用:

      jdk中的线程池:ThreadPoolExecutor,根据自己的需求传入corePoolSize、maximumPoolSize、keepAliveTimem、keepAliveTimem、unit、threadFactory、handler这几个参数,new一个指定的ThreadPoolExecutor出来。

      jdk提供了Executors这个类,让开发者对线程池的使用与生产分离开,开发者只需要调用不同的方法就可以获取到不同的线程池,开发者不用关心线程池的实现细节,只需要调用api即可获取不同的线程池。

          如:Executors.newSingleThreadExecutor()        获取单线程的线程池
                 Executors.newCachedThreadPool()        获取无界线程池

     

    优点:
        简单优化了软件体系结构,明确了各自功能模块的职责和权力,
        通过工厂类,外界不需要直接创建具体产品对象,只需要负责消费,不需要关心内部如何创建对象。
    缺点:
        如果只是使用简单的if else这样来做生产,随着产品的增多,势必要对工厂类进行不断的维护,
        使用反射的工厂效率会低一些。

    实现案例

    以登录系统为例,支持多种登录体系:口令登录、域登录。那么需要建立一个各种登录方式都适合的接口,uml图如下:

    登录接口:

    public interface Login {
        //登录验证
        public boolean verify(String name , String password);
    }
    View Code

    域登录:

    public class DomainLogin implements Login {
    
        @Override
        public boolean verify(String name, String password) {
            // TODO Auto-generated method stub
            /**
             * 业务逻辑
             */
            return true;
        }
    
    }
    View Code

    口令登录:

    public class PasswordLogin implements Login {
    
        @Override
        public boolean verify(String name, String password) {
            // TODO Auto-generated method stub
            /**
             * 业务逻辑
             */
            return true;
        }
    
    }
    View Code

    工厂类LoginManager,根据需求创建对象,如果不合法就跑出异常,会返回一个Runtime异常

    public class LoginManager {
        public static Login factory(String type){
            if(type.equals("password")){
                
                return new PasswordLogin();
                
            }else if(type.equals("passcode")){
                
                return new DomainLogin();
                
            }else{
                /**
                 * 这里抛出一个自定义异常会更恰当
                 */
                throw new RuntimeException("没有找到登录类型");
            }
        }
    }
    View Code

    测试类:

    public class Test {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            String loginType = "password";
            String name = "name";
            String password = "password";
            Login login = LoginManager.factory(loginType);
            boolean bool = login.verify(name, password);
            if (bool) {
                /**
                 * 业务逻辑
                 */
            } else {
                /**
                 * 业务逻辑
                 */
            }
        }
    }
    View Code

    实际上的结构图:

    基于上面的,使用反射来实现

    public class LoginManager {
        public static Login factory(String path) {
            Class<?> c = Class.forName(fruitPath);
            return (Fruit)c.newInstance();
        }   
    }

    这样仅需要控制入参就可以获取对应的实例了,不需要那么多if else了结构上更加清爽。

     参考链接:

    https://www.cnblogs.com/java-my-life/archive/2012/03/22/2412308.html

    https://www.cnblogs.com/xrq730/p/4902597.html

  • 相关阅读:
    接口XMPPConnection
    Smack 4.3.4 API
    Tigase XMPP Server
    Openfire Meetings插件是一个包含各种Jitsi项目(如VideoBridge和Meet)的实现
    华为方舟编译器 下载 和 LiteOS Studio Setup 2019-04-16.exe SDK下载
    华为 鸿蒙系统(HarmonyOS)
    C#.NET常见问题(FAQ)-如何使用2D绘图控件ZedGraph绘制坐标轴和坐标曲线
    C#.NET常见问题(FAQ)-如何声明list的多维数组
    C#.NET常见问题(FAQ)-如何设置控件水平对齐,垂直对齐
    C#.NET常见问题(FAQ)-如何修改Form不能修改窗体大小
  • 原文地址:https://www.cnblogs.com/lilinzhiyu/p/9848539.html
Copyright © 2011-2022 走看看