JAVA设计模式之工厂方法模式

本文详细介绍了工厂方法模式的概念、定义及应用场景,并通过实例演示了如何使用工厂方法模式创建不同类型的人类对象,最后探讨了如何进一步扩展为多个工厂类。


一、 工厂方法模式介绍

         工厂方法模式 , 是创建设计模式之一 。  工厂方法模式是一种构建简单的模式 , 其实我们平时开发中用的也是比较广泛 , 先来看一下工厂方法的模式定义 。


二、工厂方法模式的定义

         Define an interface for creating an object,but let subclasses decide which class toinstantiate.Factory Method lets a class defer instantiation to subclasses.

(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)


三、工厂方法模式的使用场景

           在任何需要生成复杂对象的地方 , 都可以使用工厂方法模式 。

        当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式

        复杂对象适合使用工厂模式 , 用 new 就可以完成创建的对象无需使用工厂模式

        假如各个等级结构中的实现类之间不存在关联或约束,则使用多个独立的工厂来对产品进行创建,则更合适一点。


四、实战

代码 :

package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;

/**
 * Created by liangshaoteng on 17-7-21.
 */
public interface Human {
    //每个人种的皮肤都有相应的颜色
    public void getColor();
    //人类会说话
    public void talk();
}

接口Human是对人类的总称,每个人种都至少具有两个方法,黑色人种、黄色人种、白色人种

package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;

/**
 * Created by liangshaoteng on 17-7-21.
 */

public class BlackHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("黑色人种的皮肤颜色是黑色的!");
    }

    @Override
    public void talk() {
        System.out.println("黑人会说话,一般人听不懂。");
    }
}

package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;

/**
 * Created by liangshaoteng on 17-7-21.
 */

public class YellowHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("黄色人种的皮肤颜色是黄色的!");
    }

    @Override
    public void talk() {
        System.out.println("黄色人种会说话,一般说的都是双字节。");
    }
}

package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;

/**
 * Created by liangshaoteng on 17-7-21.
 */

public class WhiteHuman implements Human {
    @Override
    public void getColor() {
        System.out.println("白色人种的皮肤颜色是白色的!");
    }

    @Override
    public void talk() {
        System.out.println("白色人种会说话,一般都是但是单字节。");
    }
}


注意,我们在这里采用了泛型(Generic),通过定义泛型对createHuman的输入参数产
生两层限制:
● 必须是Class类型;
● 必须是Human的实现类。
其中的"T"表示的是,只要实现了Human接口的类都可以作为参数,泛型是JDK 1.5中的
一个非常重要的新特性,它减少了对象间的转换,约束其输入参数类型,对Collection集合下
的实现类都可以定义泛型。

package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;

import static android.icu.lang.UCharacter.GraphemeClusterBreak.T;

/**
 * Created by liangshaoteng on 17-7-21.
 */

public abstract class AbstractHumanFactory {
    public abstract <T extends Human> T createHuman(Class<T> c);
}

通过反射的形式来创建实例

package com.example.liangshaoteng.myapplication.shejimoshizicandao.danyizhizhe.gongchangfangfamoshi;

/**
 * Created by liangshaoteng on 17-7-21.
 */

public class HumanFactory extends AbstractHumanFactory {

    private Human human;

    @Override
    public <T extends Human> T createHuman(Class<T> c) {

        try {
            human = (Human) c.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) human;
    }
}


public class NvWa {
public static void main(String[] args) {
//声明阴阳八卦炉
AbstractHumanFactory YinYangLu = new HumanFactory();
System.out.println("--造出的第一批人是白色人种--");
Human whiteHuman = YinYangLu.createHuman(WhiteHuman.class);
whiteHuman.getColor();
whiteHuman.talk();

System.out.println("\n--造出的第二批人是黑色人种--");
Human blackHuman = YinYangLu.createHuman(BlackHuman.class);
blackHuman.getColor();
blackHuman.talk();

System.out.println("\n--造出的第三批人是黄色人种--");
Human yellowHuman = YinYangLu.createHuman(YellowHuman.class);
yellowHuman.getColor();
yellowHuman.talk();
}
}


五、升级为多个工厂类

当我们在做一个比较复杂的项目时,经常会遇到初始化一个对象很耗费精力的情况,所有的产品类都放到一个工厂方法中进行初始化会使代码结构不清晰。例如,一个产品类有5个具体实现,每个实现类的初始化(不仅仅是new,初始化包括new一个对象,并对对象设置一定的初始值)方法都不相同,如果写在一个工厂方法中,势必会导致该方法巨大无比,那该怎么办?
考虑到需要结构清晰,我们就为每个产品定义一个创造者,然后由调用者自己去选择与哪个工厂方法关联


多工厂模式的抽象工厂类

public abstract class AbstractHumanFactory {
public abstract Human createHuman();
}
注意 抽象方法中已经不再需要传递相关参数了,因为每一个具体的工厂都已经非常明
确自己的职责:创建自己负责的产品类对象。

黑种人工厂

public class BlackHumanFactory extends AbstractHumanFactory {
public Human createHuman() {
return new BlackHuman();
}
}

黄种人工厂

public class YellowHumanFactory extends AbstractHumanFactory {
public Human createHuman() {
return new YellowHuman();
}
}
白种人工厂
public class whiteHumanFactory extends AbstractHumanFactory {
public Human createHuman() {
return new WhiteHuman();
}
}

public class NvWa {
public static void main(String[] args) {
//女娲第一次造人,火候不足,于是白色人种产生了
System.out.println("--造出的第一批人是白色人种--");
Human whiteHuman = (new WhiteHumanFactory()).createHuman();
whiteHuman.getColor();
whiteHuman.talk();
//女娲第二次造人,火候过足,于是黑色人种产生了
System.out.println("\n--造出的第二批人是黑色人种--");
Human blackHuman = (new BlackHumanFactory()).createHuman();
blackHuman.getColor();
blackHuman.talk();
//第三次造人,火候刚刚好,于是黄色人种产生了
System.out.println("\n--造出的第三批人是黄色人种--");
Human yellowHuman = (new YellowHumanFactory()).createHuman();
yellowHuman.getColor();
yellowHuman.talk();
}
}


总结

       无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工厂方法模式。

       所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。



关于 阿里云盘CLI。仿 Linux shell 文件处理命令的阿里云盘命令行客户端,支持JavaScript插件,支持同步备份功能,支持相册批量下载。 特色 多平台支持, 支持 Windows, macOS, linux(x86/x64/arm), android, iOS 等 阿里云盘多用户支持 支持备份盘,资源库无缝切换 下载网盘内文件, 支持多个文件或目录下载, 支持断点续传和单文件并行下载。支持软链接(符号链接)文件。 上传本地文件, 支持多个文件或目录上传,支持排除指定文件夹/文件(正则表达式)功能。支持软链接(符号链接)文件。 同步备份功能支持备份本地文件到云盘,备份云盘文件到本地,双向同步备份保持本地文件和网盘文件同步。常用于嵌入式或者NAS等设备,支持docker镜像部署。 命令和文件路径输入支持Tab键自动补全,路径支持通配符匹配模式 支持JavaScript插件,你可以按照自己的需要定制上传/下载中关键步骤的行为,最大程度满足自己的个性化需求 支持共享相册的相关操作,支持批量下载相册所有普通照片、实况照片文件到本地 支持多用户联合下载功能,对下载速度有极致追求的用户可以尝试使用该选项。详情请查看文档多用户联合下载 如果大家有打算开通阿里云盘VIP会员,可以使用阿里云盘APP扫描下面的优惠推荐码进行开通。 注意:您需要开通【三方应用权益包】,这样使用本程序下载才能加速,否则下载无法提速。 Windows不第二步打开aliyunpan命令行程序,任何云盘命令都有类似如下日志输出 如何登出和下线客户端 阿里云盘单账户最多只允许同时登录 10 台设备 当出现这个提示:你账号已超出最大登录设备数量,请先下线一台设备,然后重启本应用,才可以继续使用 说明你的账号登录客户端已经超过数量,你需要先登出其他客户端才能继续使用,如下所示
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值