zoukankan      html  css  js  c++  java
  • 工厂模式

    设计模式(Design Pattern):

      设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结。

    设计模式的优点:

      设计模式是优秀的使用案例,使用设计模式可提高代码的重用性,让代码更容易被他人理解,保证代码可靠性。

    工厂模式的概念:

      实例化对象,用工厂方法代替new操作

      工厂模式包括工厂方法模式和抽象工厂模式

      抽象工厂模式是工厂方法模式的扩展

    工厂模式的意图:

      定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化

      工厂方法把实例化的工作推迟到子类中去实现

    什么情况下适合工厂模式?

      有一组类似的对象需要创建

      在编码时不能预见需要创建那种类的实例

      系统需要考虑扩展性,不应依赖于产品类实例如何被创建,组合和表达细节

    工厂模式的动机:

      项目中的现状:在软件系统中经常面临着“对象”的创建工作,由于需求的变化,这个对象可能也会发生变化,但它拥有比较稳定的接口。

    为此我们需要提供一种封装机制来隔离这个易变对象的变化,从而保持系统会中其它依赖该对象的对象不随着需求变化而变化。

    基于项目现状将代码进行如下设计:

      1.尽量松耦合,一个对象的依赖对象的变化与本身无关

      2.具体产品与客户端剥离,责任分割

    1.工厂方法模式:

    01.创建接口

    package com.ltc;
    /**
     * 发型接口
     */
    public interface HairInterface {
        public void draw();
    }

    02.创建不同的发型实现该接口

    package com.ltc;
    /**
     * 右偏分发型
     */
    public class RightHair implements HairInterface {
    
        @Override
        public void draw() {
            System.out.println("-----------------左偏分发型-------------------");
    
        }
    
    }

    package com.ltc;
    /**
     * 左偏分发型
     */
    public class LeftHair implements HairInterface {

        @Override
        public void draw() {
            System.out.println("-----------------左偏分发型-------------------");

        }
    }

    03.创建发型工厂生产不同发型

    package com.ltc;
    
    import java.util.Map;
    
    public class HairFactory {
        /**
         * 根据类名称来生产对象
         */
        public HairInterface getHairByClassKey(String key){
            Map<String,String> map = new PropertiesReader().getProperties();
            try {
                //用反射创建对象
                HairInterface hair = (HairInterface) Class.forName(map.get(key)).newInstance();
                return hair;
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    上述代码中红色字体部分的作用:

    代码用反射的方式创建的对象实例,forName(“”)方法中要传全类名,我们可以利用properties文件key-value的存储方式存储全类名,然后读取该文件,返回一个Map根据获得全类名。

    读取该文件:

    package com.ltc;
    
    import java.io.InputStream;
    import java.util.Properties;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.Map;
    
    public class PropertiesReader {
    
        public Map<String, String> getProperties() {
    
            Properties props = new Properties();
            Map<String, String> map = new HashMap<String, String>();
            try {
    
                InputStream in = getClass().getResourceAsStream("type.properties");
                props.load(in);
                Enumeration en = props.propertyNames();
                while (en.hasMoreElements()) {
                    String key = (String) en.nextElement();
                    String property = props.getProperty(key);
                    map.put(key, property);
    //                System.out.println(key + "  " + property);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return map;
        }
    }

    测试:

    package com.ltc;
    
    public class Text1 {
        public static void main(String[] args) {
            HairFactory factory = new HairFactory();
            HairInterface hair1 = factory.getHairByClassKey("right");
            hair1.draw();
            HairInterface hair2 = factory.getHairByClassKey("left");
            hair2.draw();
            
        }
    }

    结果:

    2.抽象工厂模式

    以新年和圣诞人们的装扮为例:

    新年和圣诞人们都会进行不同的装扮,有新年系列装扮的男孩和女孩,也有圣诞系列新年的男孩和女孩,那我们如何实现新年就进行新年装扮,圣诞就进行圣诞装扮呢?

    01.创建男孩和女孩接口人的工厂接口

    package com.ltc;
    /**
     * 男孩
     */
    public interface Boy {
        
        public void drawMan();
    }
    package com.ltc;
    /**
     * 女孩
     */
    public interface Girl {
        
        public void drawWomen();
    }
    package com.ltc;
    /**
     * 任务的实现接口
     */
    public interface PersonFactory {
    
        //男孩接口
        public Boy getBoy();
        //女孩接口
        public Girl getGirl();
    }

    02,分创建新年男孩和新年女孩类实现男孩女孩接口,并创建新年工厂

    package com.ltc;
    /**
     * 新年系列的男孩儿
     */
    public class HNBoy implements Boy {
    
        @Override
        public void drawMan() {
            System.out.println("-----------------新年系列的男孩子--------------------");
            
        }
    
    }
    package com.ltc;
    /**
     * 新年系列的女孩儿
     */
    public class HNGirl implements Girl{
    
        @Override
        public void drawWomen() {
            System.out.println("-----------------新年系列的女孩子--------------------");
        }
        
    }
    package com.ltc;
    /**
     * 新年系列加工厂
     */
    public class HNFactory implements PersonFactory {
    
        @Override
        public Boy getBoy() {
            return new HNBoy();
        }
    
        @Override
        public Girl getGirl() {
            return new HNGirl();
        }
        
    }

    03.创建圣诞男孩和圣诞女孩实现男孩和女孩接口,创建圣诞工厂

    package com.ltc;
    /**
    *圣诞男孩儿
    */
    public class MCBoy implements Boy { @Override public void drawMan() { System.out.println("-----------------圣诞系列的男孩子--------------------"); } }
    package com.ltc;
    
    public class MCGirl implements Girl {
    
        @Override
        public void drawWomen() {
            System.out.println("-----------------圣诞系列的女孩子--------------------");
        }
    
    }
    package com.ltc;
    
    public class MCFactory implements PersonFactory {
    
        @Override
        public Boy getBoy() {
            return new MCBoy();
        }
    
        @Override
        public Girl getGirl() {
            return new MCGirl();
        }
    
    }

    04测试:

            PersonFactory factory1 = new MCFactory();
            Girl girl1 = factory1.getGirl();
            Boy boy1 = factory1.getBoy();
            girl1.drawWomen();
            boy1.drawMan();
            
            System.out.println("==================================================");
            
            PersonFactory factory2 = new HNFactory();
            Girl girl2 = factory2.getGirl();
            Boy boy2 = factory2.getBoy();
            girl2.drawWomen();
            boy2.drawMan();

    结果:

    工厂方法模式和抽象工厂模式对比:

      01.工厂方法模式是一种极端情况的抽象工厂模式,而抽象工厂模式可以看成是工厂模式的推广

      02.工厂模式用来创建一个产品的等级结构,而抽象工厂是用来创建多个产品的等级结构

      03.工厂模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类

    工厂模式的实现帮助我们:

      01.系统在不修改具体工厂角色的情况下引进新的产品

      02.客户端不必关心对象如何创建,明确了职责

      03.更好的理解,面向对象的原则,面向接口编程,而不要面向实现编程

    工厂模式适用与哪些场景:

      01.一个系统应当不依赖于产品实力被创立,组成,和表示细节。这对于所有形态的工厂模式都是重要的

      02.这个系统的产品至少有一个产品族

      03.同属于同一产品族的产品是设计成在一起使用。这一约束必须得在系统的设计中体现出来

      04.不同的产品以一系列的接口的面貌实现,从而使系统不依赖于接口实现的细节

  • 相关阅读:
    线程阻塞工具:LockSupport
    jenkins
    Mysql中MVCC的使用及原理详解
    你知道 hash 的实现吗?为什么要这样实现?
    为什么哈希表的容量一定要是 2的整数次幂?
    同步异步 阻塞 非阻塞
    MFC
    MFC
    MFC
    MFC
  • 原文地址:https://www.cnblogs.com/liutianci/p/8289823.html
Copyright © 2011-2022 走看看