JAVA模式之工厂模式

设计模式-工厂模式


工厂模式概念:

  1. 实例化对象的时候,用工厂方法代理new操作

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

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

工厂模式的意图:定义一个接口来创建对象,但是让子类来决定哪些类需要被实例化。工厂方法把实例化的工作推到子类中去实现。

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

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

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

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

一、应用场景举例

1.1工厂方法模式

要做一个类似于脸萌的软件,应该怎么来构思呢?一发型为例,发型师这个大产品中的一个小部件,如过制作出了发型,其他的部分也都相似。

下边我们使用发型来举例说明工厂方法模式

1.HairInterface.java 首先定义发型接口

public interface HairInterface {

    /**
     *实现了发型
     */
    void draw();
}

2.LeftHair.java 左偏分发型,实现发型接口


public class LeftHair implements HairInterface {
    /**
     * 画了一个左偏分发型
     */
    @Override
    public void draw() {
        System.out.printf("-----左偏分发型----");
    }
}

3.RightHair.java 右偏分发型,实现发型接口


public class RightHair implements HairInterface{
    /**
     * 画了一个右偏分发型
     */
    @Override
    public void draw() {
        System.out.printf("-----右偏分发型----");
    }
}

4.HairFactory.java 发型工厂,用于创建发型


public class HairFactory {

    /*
    * 根据类型来创建对象,
    * @param key
    * @return
    */
    public HairInterface getHair(String key) {
        if ("left".equals(key)) {
            return new LeftHair();
        } else if ("right".equals(key)) {
            return new RightHair();
        }
        return null;
    }

    /**
     * 根据类名称来生产对象
     *
     * @param className
     * @return
     */
    public HairInterface getHairByClass(String className) {
        HairInterface hair = null;
        try {
            hair = (HairInterface) Class.forName(className).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return hair;
    }

    /**
     * 根据类型名称的key值来产生对象
     * @param key
     * @return
     */
    public HairInterface getHairByClassKey(String key){
        HairInterface hair = null;
        try {
            Map<String,String> map = new PropertiesReader().getProperties();
            hair = (HairInterface) Class.forName(map.get(key)).newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return hair;
    }

}

5.type.properties 文件


left=personal.caojx.factory.LeftHair
right=personal.caojx.factory.RightHair

6.PropertiesReader.java properties文件读取类


public class PropertiesReader {

    public Map<String,String> getProperties(){
        Properties properties = new Properties();
        Map<String,String> map = new HashMap<String, String>();
        try{
            InputStream in = PropertiesReader.class.getClassLoader().getResourceAsStream("type.properties");
            properties.load(in);
            Enumeration en = properties.propertyNames();
            while (en.hasMoreElements()){
                String key = (String) en.nextElement();
                String property = properties.getProperty(key);
                map.put(key,property);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }
}

7.HairFactoryTest.java 工厂方法模式-发型工厂测试类


public class HairFactoryTest extends TestCase {

    public static void main(String[] args){

        //1.通过工厂创建实例实例一
        HairFactory factory = new HairFactory();
        HairInterface left = factory.getHair("left");
        HairInterface right = factory.getHair("right");
        left.draw();
        right.draw();

        //2.通过工厂创建实例二
        HairInterface left2 = factory.getHairByClass("personal.caojx.factory.LeftHair");
        left2.draw();

        //2.通过工厂创建实例三
        HairInterface left3 = factory.getHairByClassKey("left");
        left3.draw();


    }
}

结果

-----左偏分发型---- -----右偏分发型---- -----左偏分发型---- -----左偏分发型----

2.抽象工厂模式

加入我们过圣诞节或新年的时候需要创建圣诞的男孩女孩,和新年系列的男孩女孩,这时候我们可以考虑抽象工厂模式

1.Boy.java 男孩接口


public interface Boy {

    void drawMan();
}

Girl.java 女孩接口


public interface Girl {

    void drawWomen();
}

2.HNBoy.java 新年男孩实现类


public class HNBoy implements Boy {

    @Override
    public void drawMan() {
        System.out.println("----------新年系列的男孩-----------");
    }
}

HNGirl.java 新年女孩实现类

public class HNGirl implements Girl {

    @Override
    public void drawWomen() {
        System.out.println("----------新年系列的女孩-----------");
    }
}

MCBoy.java 圣诞男孩实现类


public class MCBoy implements Boy {

    @Override
    public void drawMan() {
        System.out.println("----------圣诞系列的男孩-----------");
    }
}

MCGirl.java 圣诞女孩实现类


public class MCGirl implements Girl {

    @Override
    public void drawWomen() {
        System.out.println("------圣诞系列的女孩---------");
    }
}

3.PersonFactory.java 人物接口实现类


public interface PersonFactory {

    //男孩接口
    Boy getBoy();

    //女孩接口
    Girl getGirl();
}

4.MCFactory.java 圣诞工厂


public class MCFactory implements PersonFactory {

    @Override
    public Boy getBoy() {
        return new MCBoy();
    }

    @Override
    public Girl getGirl() {
        return new MCGirl();
    }
}

HNFactory.java 新年工厂


public class HNFactory implements PersonFactory{

    @Override
    public Boy getBoy() {
        return new HNBoy();
    }

    @Override
    public Girl getGirl() {
        return new HNGirl();
    }
}

5.抽象工厂测试类


public class AbstractFactoryTest extends TestCase {

    public static void main(String[] args){
        //聖誕女孩
        PersonFactory factory = new MCFactory();
        Girl girl = factory.getGirl();
        girl.drawWomen();

        //新年男孩
        PersonFactory factory1 = new HNFactory();
        Boy boy = factory1.getBoy();
        boy.drawMan();
    }

}

结果

------圣诞系列的女孩--------- ------新年系列的男孩---------

3.总结

工厂方法模式和抽象工厂模式對比 1.工厂模式是一种极端情況的抽象工厂模式,而抽工厂模式可以堪称是工厂模式的推广 2.工厂模式用来创建一个产品的等级结构,而抽象工厂模式是用来创建多个产品的等级结构 3.工厂模式只有一个抽象产品类,而抽象工厂模式有多个抽象产品类

工厂模式的实现帮助了我们: 1.系统可以在不修改具体工厂角色的情况下引进新的产品 2.客户端不必关心对象的创建 3.更好的理解面向对象的原则,面向接口编程,而不要面向实现编程

猜你喜欢

转载自blog.csdn.net/eeeeasy/article/details/80808865