MyException - 我的异常网
当前位置:我的异常网» 设计模式 » 设计模式之(4)-抽象工厂模式

设计模式之(4)-抽象工厂模式

www.MyException.Cn  网友分享于:2015-02-11  浏览:0次
设计模式之(四)------抽象工厂模式

好了,我们继续上一节课,上一节讲到女娲造人,人是造出来了,世界时热闹了,可是低头一看,都
是清一色的类型,缺少关爱、仇恨、喜怒哀乐等情绪,人类的生命太平淡了,女娲一想,猛然一拍脑袋,
Shit!忘记给人类定义性别了,那怎么办?抹掉重来,然后就把人类重新洗牌,准备重新开始制造人类。
由于先前的工作已经花费了很大的精力做为铺垫,也不想从头开始了,那先说人类(Product 产品类)
怎么改吧,好,有了,给每个人类都加一个性别,然后再重新制造,这个问题解决了,那八卦炉怎么办?
只有一个呀,要么生产出全都是男性,要不都是女性,那不行呀,有了,把已经有了一条生产线——八卦
炉(工厂模式中的 Concrete Factory)拆开,于是女娲就使用了“八卦拷贝术”,把原先的八卦炉一个变两
个,并且略加修改,就成了女性八卦炉(只生产女性,一个具体工厂的实现类)和男性八卦炉(只生产男
性,又一个具体工厂的实现类)先看一下 我们的类的结构图:
eclipse 项目类结构
3个抽象类 YellowHuman BlackHuman WhiteHuman 在抽象工厂模式中叫做产品等级,6个实现类(FemaleYellowHuman MaleYellowHuman FemaleBlackHuman MaleBlackHuman FemaleWhiteHuman MaleWhiteHuamn )叫做产品族。
其中抽象工厂AbstractHumanFactory 只有一个createHuman 的方法。下面我们来看程序实现:

package com.fc.AbstractFactory;

public interface IHumann {
 public void  laugh();
 public  void talk();
 public  void sex();
}

人类的接口定义好,然后根据接口创建三个抽象类,也就是三个产品等级, 实现 laugh()、talk()
三个方法,以 AbstractYellowHuman 为例:

package com.fc.AbstractFactory.dengji;

import com.fc.AbstractFactory.IHumann;

public abstract class AbstractYellowHuman implements IHumann{

    public void laugh() {
        System.out.println("黄色人类会笑");

    }

    public void talk() {
        System.out.println("黄色人类说话");

    }

}

其他两个与这个类似,这样三个抽象类就实现完了,然后就是那6个实现类了。
我们先来看女性黄色人种的实现类:

package com.fc.AbstractFactory.pinzu;

import com.fc.AbstractFactory.dengji.AbstractYellowHuman;


public class YellowFemaleHuman extends AbstractYellowHuman {
    public void sex() {
        System. out.println(" 该黄种人的性别为女...");
        }
}

男性黄色人种:

package com.fc.AbstractFactory.pinzu;

import com.fc.AbstractFactory.dengji.AbstractYellowHuman;


public class YellowMaleHuman extends AbstractYellowHuman{

    public void sex() {
        System.out.println("该黄种人的性别是男。。。");

    }

}

女性黑色人种:

package com.fc.AbstractFactory.pinzu;

import com.fc.AbstractFactory.dengji.AbstractBlackHuman;


public class BlackFemaleHuman extends AbstractBlackHuman{
    public void sex() {
        System. out.println(" 该黑人的性别为女...");
        }
}

男性黑色人种:

package com.fc.AbstractFactory.pinzu;

import com.fc.AbstractFactory.dengji.AbstractBlackHuman;


public class BlackMaleHuman extends AbstractBlackHuman{

    public void sex() {
        System.out.println("该黑人的性别是男。。。");

    }

}

女性白色人种:

package com.fc.AbstractFactory.pinzu;

import com.fc.AbstractFactory.dengji.AbstractWhiteHuman;


public class WhiteFemaleHuman extends AbstractWhiteHuman {
    public void sex() {
        System. out.println(" 该白人的性别为女...");
        }
}

男性白色人种:

package com.fc.AbstractFactory.pinzu;

import com.fc.AbstractFactory.dengji.AbstractWhiteHuman;


public class WhiteMaleHuman extends AbstractWhiteHuman{

    public void sex() {
        System.out.println("该白人的性别是男。。。");

    }

}

抽象工厂模式下的产品等级和产品族都已经完成,也就是人类以及产生出的人类是什么样子的都已经
定义好了,下一步就等着工厂开工创建了,那我们来看工厂类。
在看工厂类之前我们先看那个枚举类型,这个是很有意思的:

package com.fc.AbstractFactory;

public enum HumanEnum {

  YelloMaleHuman("com.fc.AbstractFactory.pinzu.YellowMaleHuman"),
  YelloFemalHuman("com.fc.AbstractFactory.pinzu.YellowFemaleHuman"),
  WhiteFemalHuman("com.fc.AbstractFactory.pinzu.WhiteFemaleHuman"),
  WhiteMaleHuman("com.fc.AbstractFactory.pinzu.WhiteMaleHuman"),
  BlackFemalHuman("com.fc.AbstractFactory.pinzu.BlackFemaleHuman"),
  BlackMaleHuman("com.fc.AbstractFactory.pinzu.BlackMaleHuman");
private String value = "";
    //定义构造函数,目的是Data(value) 类型的相匹配
    private HumanEnum(String value){
     this. value = value;
     }
    public String getValue(){
     return this. value;
     }
}

Enum 以前我也很少用,最近在一个项目中偶然使用上了,然后才发觉它的好处,Enum 类型作为一个参
数传递到一个方法中时,在 Junit 进行单元测试的时候,不用判断输入参数是否为空、长度为 0 的边界异
常条件,如果方法传入的参数不是 Enum 类型的话,根本就传递不进来,你说定义一个类,定义一堆的静态
变量,这也可以呀,这个不和你抬杠,上面的代码我解释一下,构造函数没啥好说的,然后是 getValue()
方法,就是获得枚举类型中一个元素的值,枚举类型中的元素也是有名称和值的,这个和 HashMap 有点类
似。
然后,我们看我们的工厂类,先看接口:

package com.fc.AbstractFactory;

public interface IHumanFatory {
    //制造黄色人类
    public IHumann createYellowHuman();
    //制造一个白色人类
    public IHumann createWhiteHuman();
    //制造一个黑色人类
    public IHumann createBlackHuman();
}

然后看抽象类:

package com.fc.AbstractFactory;

import com.fc.factory.Human;

public abstract class AbstractHumanFactory implements IHumanFatory {
    /*
     * 给定一个性别人类,创建一个人类出来 专业术语是产生产品等级
     */
    protected IHumann createHuman(HumanEnum humanEnum) {
        IHumann human = null;
        // 如果传递进来不是一个Enum中具体的一个Element的话,则不处理
        if (!humanEnum.getValue().equals("")) {
            try {
                // 直接产生一个实例
                human = (IHumann) Class.forName(humanEnum.getValue())
                        .newInstance();
            } catch (Exception e) {
                // 因为使用了enum,这个种异常情况不会产生了,除非你的enum有问题;
                e.printStackTrace();
            }
        }
        return human;
    }
}

看到没,这就是引入 enum 的好处,createHuman(HumanEnum humanEnum)这个方法定义了输入参数必须
是 HumanEnum 类型,然后直接使用 humanEnum.getValue()方法就能获得具体传递进来的值,这个不多说了,
大家自己看程序领会,没多大难度,这个抽象类的目的就是减少下边实现类的代码量,我们看实现类:
男性工厂,只创建男性:

package com.fc.AbstractFactory;

 public class MaleHumanFactory extends AbstractHumanFactory{


public IHumann createYellowHuman() {

    return super.createHuman(HumanEnum.YelloMaleHuman);
}

public IHumann createWhiteHuman() {

    return super.createHuman(HumanEnum.WhiteMaleHuman);
}

public IHumann createBlackHuman() {

    return super.createHuman(HumanEnum.BlackMaleHuman);
}
}

女性工厂,只创建女性:

package com.fc.AbstractFactory;

public class FemaleHumanFactory extends AbstractHumanFactory{

    public IHumann createYellowHuman() {
        // TODO Auto-generated method stub
        return super.createHuman(HumanEnum.YelloFemalHuman);
    }

    public IHumann createWhiteHuman() {
        // TODO Auto-generated method stub
        return super.createHuman(HumanEnum.WhiteFemalHuman);
    }

    public IHumann createBlackHuman() {
        // TODO Auto-generated method stub
        return super.createHuman(HumanEnum.BlackFemalHuman);
    }

}

产品定义好了,工厂也定义好了,万事俱备只欠东风,那咱就开始造吧,哦,不对,女娲开始造人了:

package com.fc.AbstractFactory;

public class NvWa {

    /**
     * @param args
     */
    public static void main(String[] args) {

         //第一条生产线,男性生产线
         IHumanFatory maleHumanFactory = new MaleHumanFactory();
         //第二条生产线,女性生产线
         IHumanFatory femaleHumanFactory = new FemaleHumanFactory();
         //生产线建立完毕,开始生产人了:
         IHumann maleYellowHuman = maleHumanFactory.createYellowHuman();
         IHumann femaleYellowHuman = femaleHumanFactory.createYellowHuman();
         maleYellowHuman.talk();
         maleYellowHuman.laugh();
         femaleYellowHuman.sex();
         /*
         * .....
         * 后面你可以续了
         */

    }

}

输出结果:
*黄色人类说话
黄色人类会笑
该黄种人的性别为女…*

文章评论

 程序员的样子
程序员的样子
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
如何成为一名黑客
如何成为一名黑客
编程语言是女人
编程语言是女人
我的丈夫是个程序员
我的丈夫是个程序员
10个调试和排错的小建议
10个调试和排错的小建议
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
Java程序员必看电影
Java程序员必看电影
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
程序员的鄙视链
程序员的鄙视链
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
老程序员的下场
老程序员的下场
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
程序员必看的十大电影
程序员必看的十大电影
鲜为人知的编程真相
鲜为人知的编程真相
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
为什么程序员都是夜猫子
为什么程序员都是夜猫子
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
程序员都该阅读的书
程序员都该阅读的书
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
旅行,写作,编程
旅行,写作,编程
那些争议最大的编程观点
那些争议最大的编程观点
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
程序员和编码员之间的区别
程序员和编码员之间的区别
一个程序员的时间管理
一个程序员的时间管理
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
代码女神横空出世
代码女神横空出世
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
总结2014中国互联网十大段子
总结2014中国互联网十大段子
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有