创建型模式5之1-FactoryMethod工厂方法模式例子理解

例子一

package com.test.factorymodel;
/**
 *  工厂方法:一抽象产品类派生出多个具体产品类;一抽象工厂类派生出多个具体工厂类;每个具体工厂类只能创建一个具体产品类的实例。

    即定义一个创建对象的接口(即抽象工厂类),让其子类(具体工厂类)决定实例化哪一个类(具体产品类)。“一对一”的关系。

    在以下情况下,适用于工厂方法模式:

(1) 当一个类不知道它所必须创建的对象的类的时候。

(2) 当一个类希望由它的子类来指定它所创建的对象的时候。

(3) 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。
 * @author Administrator
 *
 */
public class FactoryMethod {

    // 抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。
    public static abstract class Phone {
        public Phone() {
            // TODO Auto-generated constructor stub
        }
    }

    // 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
    public static class iPhone extends Phone {
        public iPhone() {
            // TODO Auto-generated constructor stub
            System.out.println("iPhone");
        }
    }

    // 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。
    public static class AndroidPhone extends Phone {
        public AndroidPhone() {
            // TODO Auto-generated constructor stub
            System.out.println("AndroidPhone");
        }
    }

    // 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。
    public interface IFactory {

        Phone createPhone();

    }

    // 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
    public static class iPhoneFactory implements IFactory {

        @Override
        public Phone createPhone() {
            // TODO Auto-generated method stub
            return new iPhone();
        }

    }

    // 具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。
    public static class AndroidPhoneFactory implements IFactory {

        @Override
        public Phone createPhone() {
            // TODO Auto-generated method stub
            return new AndroidPhone();
        }

    }

    public static class FactoryMethod_Customer {
        public static void main(String[] args) {
            iPhoneFactory factoryiPhone = new iPhoneFactory();
            Phone iPhone = factoryiPhone.createPhone();

            AndroidPhoneFactory factoryAndroidPhone = new AndroidPhoneFactory();
            Phone androidPhone = factoryAndroidPhone.createPhone();
        }
    }
}

例子二
这里写图片描述

interface Human {
    public void Talk();
    public void Walk();
}

class Boy implements Human{
    @Override
    public void Talk() {
        System.out.println("Boy is talking...");        
    }

    @Override
    public void Walk() {
        System.out.println("Boy is walking...");
    }
}

class Girl implements Human{

    @Override
    public void Talk() {
        System.out.println("Girl is talking...");   
    }

    @Override
    public void Walk() {
        System.out.println("Girl is walking...");
    }
}

public class HumanFactory {
    public static Human createHuman(String m){
        Human p = null;
        if(m == "boy"){
            p = new Boy();
        }else if(m == "girl"){
            p = new Girl();
        }

        return p;
    }
}

工厂模式:
首先需要说一下工厂模式。工厂模式根据抽象程度的不同分为三种:简单工厂模式(也叫静态工厂模式)、本文所讲述的工厂方法模式、以及抽象工厂模式。工厂模式是编程中经常用到的一种模式。它的主要优点有:
可以使代码结构清晰,有效地封装变化。在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
对调用者屏蔽具体的产品类。如果使用工厂模式,调用者只关心产品的接口就可以了,至于具体的实现,调用者根本无需关心。即使变更了具体的实现,对调用者来说没有任何影响。
降低耦合度。产品类的实例化通常来说是很复杂的,它需要依赖很多的类,而这些类对于调用者来说根本无需知道,如果使用了工厂方法,我们需要做的仅仅是实例化好产品类,然后交给调用者使用。对调用者来说,产品所依赖的类都是透明的。

工厂方法模式:
通过工厂方法模式的类图可以看到,工厂方法模式有四个要素:
工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来作为与调用者交互的接口,其本质上是一样的。
工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。
产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。
前文提到的简单工厂模式跟工厂方法模式极为相似,区别是:简单工厂只有三个要素,他没有工厂接口,并且得到产品的方法一般是静态的。因为没有工厂接口,所以在工厂实现的扩展性方面稍弱,可以算所工厂方法模式的简化版,关于简单工厂模式,在此一笔带过。

适用场景:
不管是简单工厂模式,工厂方法模式还是抽象工厂模式,他们具有类似的特性,所以他们的适用场景也是类似的。
首先,作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
其次,工厂模式是一种典型的解耦模式,迪米特法则在工厂模式中表现的尤为明显。假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。将会大大降低对象之间的耦合度。
再次,由于工厂模式是依靠抽象架构的,它把实例化产品的任务交由实现类完成,扩展性比较好。也就是说,当需要系统有比较好的扩展性时,可以考虑工厂模式,不同的产品用不同的实现工厂来组装。

===================================

补充例子:
1.HairInterface

    package com.test.factorymodel.two4factorymethod;

public interface HairInterface {
    public void colorHair();
}

2.RedHair

package com.test.factorymodel.two4factorymethod;

public class RedHair implements HairInterface{

    @Override
    public void colorHair() {
        // TODO Auto-generated method stub
        System.out.println("染成红色头发");
    }

}

3.YellowHair

package com.test.factorymodel.two4factorymethod;

public class YellowHair implements HairInterface {

    @Override
    public void colorHair() {
        // TODO Auto-generated method stub
        System.out.println("染成黄色头发");
    }

}

4.HairFactory

package com.test.factorymodel.two4factorymethod;

import java.util.Map;

public class HairFactory {

    /**
     * 根据类型来创建对象
     * 
     * @param key
     * @return
     */
    public HairInterface getHair(String key) {
        if ("red".equals(key)) {
            return new RedHair();
        } else if ("yellow".equals(key)) {
            return new YellowHair();
        }
        return null;
    }

    /**
     * 根据类的名称来生产对象
     * @param className
     * @return
     */
    public HairInterface getHairByClass(String className){

        try {
            HairInterface hair = (HairInterface) Class.forName(className).newInstance();
            return hair;
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据类的名称来生产对象
     * @param className
     * @return
     */
    public HairInterface getHairByClassKey(String key){

        try {
            Map<String, String> map = new PropertiesReader().getProperties();

            HairInterface hair = (HairInterface) Class.forName(map.get(key)).newInstance();
            return hair;
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}

6.PropertiesReader

package com.test.factorymodel.two4factorymethod;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * properties文件的读取工具
 * @author Administrator
 *
 */
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;
    }
}

7.type.properties

red=com.test.factorymodel.two4factorymethod.RedHair
yellow=com.test.factorymodel.two4factorymethod.YellowHair

8.Test

package com.test.factorymodel.two4factorymethod;

public class Test {
    public static void main(String[] args) {

        //原始的
        HairInterface red = new RedHair();
        red.colorHair();
        //工厂
        HairFactory factory = new HairFactory();
        HairInterface yellow = factory.getHair("yellow");
        yellow.colorHair();

        HairInterface red2 =
        factory.getHairByClass("com.test.factorymodel.two4factorymethod.RedHair");
        red2.colorHair();

        HairInterface hair = factory.getHairByClassKey("yellow");
        hair.colorHair();

    }
}

9.结果

染成红色头发
染成黄色头发
染成红色头发
染成黄色头发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值