zoukankan      html  css  js  c++  java
  • 设计模式-简单工厂模式

    一、定义:由一个工厂对象决定创建出哪一种产品类的实例

    二、类型:创建型,但不属于GOF23种设计模式

    三、适用场景:

      工厂类负责创建的对象比较少

      客户端(应用层)只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心。

    四、优点:

      只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节

    五、缺点:

      工厂类的职责相对过重,增加新的产品需要修改工厂类的判断逻辑,违背开闭原则

    六、Coding

    1.创建Video抽象类

    public abstract class Video {
        public abstract void  produce();
    }  

    里面包含一个抽象方法 produce代表录制视频

    2.创建JavaVideo类,继承Video抽象类

    public class JavaVideo  extends  Video{
        @Override
        public void produce() {
            System.out.println("录制Java视频");
        }
    }
    

      

    3. 创建AndroidVideo类,继承Video抽象类

    public class AndroidVideo  extends  Video{
        @Override
        public void produce() {
            System.out.println("录制Android视频");
        }
    }
    

      

    4. 创建工厂类

    public class VideoFactory {
    
        public Video getVideo(String type){
            if("java".equalsIgnoreCase(type)){
                return  new JavaVideo();
            }else if("android".equalsIgnoreCase(type)){
                return  new AndroidVideo();
            }
    
            return  null;
        }
    }
    

      

    5. 创建测试类或者应用类

    public class Test {
        public static void main(String[] args) {
            VideoFactory videoFactory = new VideoFactory();
            Video video = videoFactory.getVideo("java");
            if(video == null){
                return;
            }
            video.produce();
        }
    }
    

      

    6. UML图如下:

    7. 缺点: 如果要增加Ios视频录制,则要修改工厂类的判断逻辑以及增加IosVideo类

       这样违背开放闭合原则

      改进方法: 将工厂类中通过字符创建实例的方法改为通过反射创建实例,这样增加IosVideo时,工厂类就不需要做修改

      改进后的VideoFactory 类

     public Video getVideo(Class c)  {
           Video video = null;
            try {
                video = (Video) Class.forName(c.getName()).newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return  video;
        }
    

      测试类的调用方法

    public class Test {
    
        public static void main(String[] args) {
            VideoFactory videoFactory = new VideoFactory();
            Video video = videoFactory.getVideo(JavaVideo.class);
            if(video == null){
                return;
            }
            video.produce();
        }
    }
    

      

    七、JDK源码中使用简单工厂模式的地方

    1. Calendar类

    public static Calendar getInstance(TimeZone zone,
                                           Locale aLocale)
        {
            return createCalendar(zone, aLocale);
        }
    

    createCalendar方法  

     private static Calendar createCalendar(TimeZone zone,  Locale aLocale)
        {
            Calendar cal = null;
    
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype == null) {
                // Calendar type is not specified.
                // If the specified locale is a Thai locale,
                // returns a BuddhistCalendar instance.
                if ("th".equals(aLocale.getLanguage())
                        && ("TH".equals(aLocale.getCountry()))) {
                    cal = new BuddhistCalendar(zone, aLocale);
                } else {
                    cal = new GregorianCalendar(zone, aLocale);
                }
            } else if (caltype.equals("japanese")) {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else if (caltype.equals("buddhist")) {
                cal = new BuddhistCalendar(zone, aLocale);
            } else {
                // Unsupported calendar type.
                // Use Gregorian calendar as a fallback.
                cal = new GregorianCalendar(zone, aLocale);
            }
    
            return cal;
        }
    

     根据caltype类型,创建对应的实例。

    uml图

     

    2. logback中ILoggerFactory.class中的getLogger方法

    public final Logger getLogger(String name) {
            if(name == null) {
                throw new IllegalArgumentException("name argument cannot be null");
            } else if("ROOT".equalsIgnoreCase(name)) {
                return this.root;
            } else {
                int i = 0;
                Logger logger = this.root;
                Logger childLogger = (Logger)this.loggerCache.get(name);
                if(childLogger != null) {
                    return childLogger;
                } else {
                    int h;
                    do {
                        h = LoggerNameUtil.getSeparatorIndexOf(name, i);
                        String childName;
                        if(h == -1) {
                            childName = name;
                        } else {
                            childName = name.substring(0, h);
                        }
    
                        i = h + 1;
                        synchronized(logger) {
                            childLogger = logger.getChildByName(childName);
                            if(childLogger == null) {
                                childLogger = logger.createChildByName(childName);
                                this.loggerCache.put(childName, childLogger);
                                this.incSize();
                            }
                        }
    
                        logger = childLogger;
                    } while(h != -1);
    
                    return childLogger;
                }
            }
        }
    

      根据name,获得哪一个log

  • 相关阅读:
    Hanoi塔
    采药
    进制转换(大数)
    Load Balancing with NGINX 负载均衡算法
    upstream模块实现反向代理的功能
    epoll
    在nginx启动后,如果我们要操作nginx,要怎么做呢 别增加无谓的上下文切换 异步非阻塞的方式来处理请求 worker的个数为cpu的核数 红黑树
    粘性会话 session affinity sticky session requests from the same client to be passed to the same server in a group of servers
    负载均衡 4层协议 7层协议
    A Secure Cookie Protocol 安全cookie协议 配置服务器Cookie
  • 原文地址:https://www.cnblogs.com/linlf03/p/9741060.html
Copyright © 2011-2022 走看看