您的位置:首页 > 编程语言 > Java开发

java23种常用设计模式之抽象工厂模式(Abstract Factory)2

2014-12-23 13:56 936 查看
继续上一篇的工厂方法模式的优化,上一节讲到一个例子,生产白人、黑人和黄人,会说会笑,但是人有男有女,这个怎么拓展呢?重新生产一次?太不理智了!

之前花费了那么多功夫,不能白忙一场呀!

这里我们引入一个抽象工厂,问题就简单了!抽象工厂只实现了一个createHuman 的方法,目的是简化实现类的代码工作量,这个在讲代码的时候再说。这里还使用了Jdk 1.5以上版本 的一个新特性Enum 类型,其实这个完全可以由类的静态变量来实现,但我想既然是学习就应该学有所获得,学以致用,即使你对这个模式非常了解,也可能没用过Enum 类型,也算是一个不同以往的知识点吧,我希望给大家讲解,每次都有新的技术点提出来,每个人都会有一点的新的收获,然后在具体的项目中使用时,知道有这个技术点,然后上baidu
Google一下就能解决问题。(话题扯远了……)上代码……

Human不是那个Human啦,我有男女之分……

package com.freedom.factory.abstractfactory;

public interface Human2 {
    
    public void say();
    public void smile();
    //性别
    public void gender();

}
定义三个抽象人种(抽象类)

package com.freedom.factory.abstractfactory;

import com.freedom.factory.factory2.Human;

public abstract class AbstractWhiteHuman implements Human{

@Override
public void say() {
System.out.println("white human can say anything!");

}

@Override
public void smile() {
System.out.println("white human can smile!");

}

}

package com.freedom.factory.abstractfactory;

import com.freedom.factory.factory2.Human;

public abstract class AbstractBlackHuman implements Human{
    
    
    @Override
    public void say() {
        System.out.println("black human can say anything!");
        
    }

    @Override
    public void smile() {
        System.out.println("black human can smile!");
        
    }

}

package com.freedom.factory.abstractfactory;

import com.freedom.factory.factory2.Human;

public abstract class AbstractYellowHuman implements Human{
    
    
    @Override
    public void say() {
        System.out.println("yellow human can say anything!");
        
    }

    @Override
    public void smile() {
        System.out.println("yellow human can smile!");
        
    }

}
由于以上人种都是抽象类,java是不允许你new出一个人来的,之恩能够乖乖实现它,这下就好玩了,你想实现一个female还是一个male呢!随便了!(粤语:shi dan la!)

package com.freedom.factory.abstractfactory;

public class YellowFemaleHuman extends AbstractWhiteHuman{

@Override
public void gender() {
System.out.println("Yellow Lady first!");

}

}
package com.freedom.factory.abstractfactory;

public class YellowMaleHuman extends AbstractWhiteHuman{

    @Override
    public void gender() {
        System.out.println("Yellow Male!");
        
    }
    
}

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

package com.freedom.factory.abstractfactory;

public enum HumanEnum {
// 把世界上所有人类型都定义出来
YelloMaleHuman("com.freedom.factory.abstractfactory.YellowMaleHuman"),
YelloFemaleHuman("com.freedom.factory.abstractfactory.YellowFemaleHuman"),
WhiteFemaleHuman("com.freedom.factory.abstractfactory.WhiteFemaleHuman"),
WhiteMaleHuman("com.freedom.factory.abstractfactory.WhiteMaleHuman"),
BlackFemaleHuman("com.freedom.factory.abstractfactoryBlackFemaleHuman"),
BlackMaleHuman("com.freedom.factory.abstractfactory.BlackMaleHuman");

private String value = "";

// 定义构造函数,目的是Data(value)类型的相匹配
private HumanEnum(String value) {
this.value = value;
}

public String getValue() {
return this.value;
}
/*
* java enum类型尽量简单使用,尽量不要使用多态、继承等方法 毕竟用Class完全可以代替enum
*/
}
然后,我们看我们的工厂类,先看接口:

package com.freedom.factory.abstractfactory;

import com.freedom.factory.factory2.Human;

public interface HumanFactory {

//制造黄色人种
public Human createYellowHuman();
//制造一个白色人种
public Human createWhiteHuman();
//制造一个黑色人种
public Human createBlackHuman();

}
然后看抽象类:

package com.freedom.factory.abstractfactory;

public abstract class AbstractHumanFactory implements HumanFactory {

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

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

package com.freedom.factory.abstractfactory;

public class FemaleHumanFactory extends AbstractHumanFactory {
// 创建一个女性黑种人
public Human2 createBlackHuman() {
return super.createHuman(HumanEnum.BlackFemaleHuman);
}

// 创建一个女性白种人
public Human2 createWhiteHuman() {
return super.createHuman(HumanEnum.WhiteFemaleHuman);
}

// 创建一个女性黄种人
public Human2 createYellowHuman() {
return super.createHuman(HumanEnum.YelloFemaleHuman);
}
}
male工厂

package com.freedom.factory.abstractfactory;

public class MaleHumanFactory extends AbstractHumanFactory {
// 创建一个男性黑种人
public Human2 createBlackHuman() {
return super.createHuman(HumanEnum.BlackMaleHuman);
}

// 创建一个男性白种人
public Human2 createWhiteHuman() {
return super.createHuman(HumanEnum.WhiteMaleHuman);
}

// 创建一个男性黄种人
public Human2 createYellowHuman() {
return super.createHuman(HumanEnum.YelloMaleHuman);
}
}
test

package com.freedom.factory.abstractfactory;

import org.junit.Test;

public class TestAbstractFactory {

@Test
public void test3() {
//第一条生产线,男性生产线
HumanFactory maleHumanFactory = new MaleHumanFactory();
//第二条生产线,女性生产线
HumanFactory femaleHumanFactory = new FemaleHumanFactory();
//生产线建立完毕,开始生产人了:
Human2 maleYellowHuman = maleHumanFactory.createYellowHuman();
Human2 femaleYellowHuman = femaleHumanFactory.createYellowHuman();
maleYellowHuman.say();
maleYellowHuman.smile();
femaleYellowHuman.gender();
/*
* .....
* 后面shi dan (随便)你了!
*/
}

}


抽象工厂模式讲完了,我们再思考一些问题:工厂模式有哪些优缺点?

小结一下,先说优点,我这人一般先看人优点,非常重要的一点是,工厂模式符合OCP (开闭原则),怎么说呢,比如就性别的问题,这个世界上还存在双性人(for example泰国人妖),是男的也是女的,那这个就是要再增加一个工厂(FemaleAndMaleFactory)就可以解决这个问题,我就不写了,很简单的!大家自己有兴趣可以画下类图,然后实现下,也相当于温故,然后看看能不能知新。

那还有没有其他好处呢?抽象工厂模式,有一个非常大的有点,高内聚,低耦合,在一个较大的项目组,产品是由一批人定义开发的,但是提供其他成员访问的时候,只有工厂方法和产品的接口,也就是说只需要提供Product Interface 和Concrete Factory 就可以产生自己需要的对象和方法,Java 的高内聚低耦合的特性表现的一览无遗,哈哈,终于Over了!

下载源码:http://download.csdn.net/detail/github_22022001/8290541
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: