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

Java设计模式(3)之工厂方法模式&抽象工厂模式学习总结

2017-10-21 21:24 771 查看

工厂模式&抽象工厂模式

工厂模式主要用于实现将对象的实例化部分取出来,进而优化系统架构,增强系统的扩展性。

工厂模式的适用场景:

1. 需要创建一组类似的对象,对应于需要生产一个产品族的不同产品;
2. 在编写代码时,不能预见需要创建哪种类的实例,即不能预见需要生产哪种产品;指定的类型由客户端的具体要求决定,从而实现功能的剥离;
3. 需要考虑系统的扩展性,系统的实现不能依赖于产品类实例如何被创建、组合及表达的细节;


工厂模式的作用:

使用工厂提供的方法代替new操作进行实例的获取;


工厂模式的目的:

①尽量使设计达到松耦合,即对象的变化不会影响到依赖于该对象的对象的变化,这也是为什么使用接口进行工厂模式设计的原因之一;
②剥离具体产品的生产与客户端,实现责任分割;即由客户端指定需要生产的具体产品,由工厂进行该产品的生产;


工厂模式的分类:

工厂方法模式和抽象工厂模式;


工厂模式和抽象工厂模式是在日常开发中使用非常广泛的设计模式。

两者的联系:

①工厂方法模式可以视为抽象工厂模式的一种特例;抽象工厂模式是工厂方法模式的扩展;
②工厂方法模式一般针对一个产品族的产品生产进行设计;抽象工厂模式一般针对多个产品族的产品的生产进行设计;


相关关键词:工厂类、产品族、系列

工厂模式的设计思路:

①定义一个稳定的公共接口作为产品族中的不同产品类的实现接口(产品族接口),把具体产品的实例化,放到工厂方法中进行实现;
②分别进行不同的产品类的设计,必须实现产品族接口;
③定义一个产品族的工厂类,该类主要提供获取不同种类产品的方法(工厂方法);
注意:
①这里的工厂方法的设计要尽可能地通用化,一般设计为只需要提供一个关键词就可以获取一个产品的工厂方法;
②这里的工厂方法可以使用反射机制进行设计,根据指定的产品类的类名进行对象的实例化;
为避免类名过长,可以通过映射简化类名,在properties文件中,进行关键词和类名的映射;


设计案例:

以最近比较火的手游王者荣耀作为例子,其中的英雄属于一个产品族,这个产品族中包含坦克类英雄、射手类英雄以及辅助类英雄等;
这里将英雄设计为一个接口HeroInterface;不同的英雄类通过实现该接口进行设计,生产不同类型英雄的工厂类提供工厂方法进行英雄的生产;


package design.pattern.hero;
//英雄类公共接口
public interface HeroInterface
{
public HeroInterface produce();
}

package design.pattern.hero;
//坦克英雄类
public class TankHero implements HeroInterface
{
@Override
public HeroInterface produce()
{
System.out.println("坦克型英雄");
//return new TankHero();
}

package design.pattern.hero;
//法
d1ce
师英雄类
public class MasterHero implements HeroInterface
{
@Override
public HeroInterface produce()
{
System.out.println("法师型英雄");
//return new MasterHero();
}

package design.pattern.hero;
//辅助英雄类
public class AuxiliaryHero implements HeroInterface
{
@Override
public HeroInterface produce()
{
System.out.println("辅助型英雄");
//return new AuxiliaryHero();
}
}

package design.pattern.hero;
//生产英雄的工厂类
public class HeroFactory
{
//方法一:通过类型获取对应的英雄
public static HeroInterface produceHeroByType(String type)
{
if("Tank".equals(type))
{
return new TankHero().produce();
}else if("Master".equals(type))
{
return new MasterHero().produce();
}else if("Auxiliary".equals(type))
{
return new AuxiliaryHero().produce();
}
return null;
}

//方法二:通过类名获取相应类的英雄
public static HeroInterface produceHeroByClassName(String className)
{
try {
HeroInterface hero = (HeroInterface) Class.forName(className).newInstance();
return hero.produce();
} 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;
}

//方法三:通过类名对应的关键字获取相应类的英雄
public static HeroInterface produceHeroByClassKey(String key)
{
try {
Map<String, String> map = new PropertiesReader().getProperties();
HeroInterface hero = (HeroInterface) Class.forName(map.get(key)).newInstance();
return hero.produce();
} 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;
}

}

package design.pattern.hero;
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);
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
}
design.pattern.hero包下的type.properties文件:
Tank=design.pattern.hero.TankHero
Master=design.pattern.hero.MasterHero
Auxiliary=design.pattern.hero.AuxiliaryHero


抽象工厂模式的设计思路:

抽象工厂模式一般适用于需要生产多个产品族的产品的场景;这里以最简单的(两个产品族)作为例子讲解:
产品族A和产品族B  系列X和系列Y
①分别设计对应于产品族A、B的产品族接口;
②根据系列的不同,将产品族A、B的产品类实现为不同系列下的产品类;
③设计一个包含获取产品族A、B的产品的方法的公共接口(产品族公共接口);
④基于实现产品族公共接口,进行不同系列下的工厂类的设计;
这里的工厂类依据不同的系列,分为两个工厂类(系列X、Y的工厂类);
系列X的工厂类的工厂方法用于生产系列X下的产品族A和产品族B的产品;
系列Y的工厂类的工厂方法用于生产系列Y下的产品族A和产品族B的产品;


设计案例:

基于上一个设计案例的背景,对英雄的皮肤进行进行抽象工厂模式的设计,同时增加国庆风格、中秋风格两个系列;英雄皮肤分为男式英雄皮肤

和女式英雄皮肤,将其设计为接口HeroDressInterface、HeroineDressInterface;国庆风格下的实现类为NationalHeroDress、NationalHeroineDress;

中秋风格下的实现类为MAHeroDress、MAHeroineDress;国庆、中秋两个系列对应的皮肤工厂类分别为NationalFactory、 MAFactory;这两个工厂类都实现了皮肤工厂接口;

HeroDressInterface接口具体代码如下:

//男式英雄皮肤接口
public interface HeroDressInterface
{
public HeroDressInterface produceHeroDress();
}


HeroineDressInterface接口具体代码如下:

//女式英雄皮肤接口
public interface HeroineDressInterface
{
public HeroineDressInterface produceHeroineDress();

//国庆系列男式英雄皮肤类
public class NationalHeroDress implements HeroDressInterface
{
@Override
public HeroDressInterface produceHeroDress()
{
System.out.println("国庆系列男式英雄皮肤");
}
}


//国庆系列女式英雄皮肤
public class NationalHeroineDress implements HeroineDressInterface
{
@Override
public HeroineDressInterface produceHeroineDress()
{
System.out.println("国庆系列女式英雄皮肤");
}
}


//中秋系列男式英雄皮肤类
public class MAHeroDress implements HeroDressInterface
{
@Override
public HeroDressInterface produceHeroDress()
{
System.out.println("中秋系列男式英雄皮肤");
}
}


//中秋系列女式英雄皮肤
public class MAHeroineDress implements HeroineDressInterface
{
@Override
public HeroineDressInterface produceHeroineDress()
{
System.out.println("中秋系列女式英雄皮肤");
}
}


//皮肤的实现接口
public interface dressFactory
{
//获取男式英雄皮肤
public HeroDressInterface produceHeroDre();
//获取女式英雄皮肤
public HeroineDressInterface produceHeroineDre();
}


//国庆系列皮肤工厂类
public class nationalDressFactory implements dressFactory
{
@Override
public HeroDressInterface produceHeroDre()
{
return new NationalHeroDress();
}
@Override
public HeroineDressInterface produceHeroineDre()
{
return new NationalHeroineDress();
}
}


//中秋系列皮肤工厂类
public class maDressFactory implements dressFactory
{
@Override
public HeroDressInterface produceHeroDre()
{
return new MAlHeroDress();
}
@Override
public HeroineDressInterface produceHeroineDre()
{
return new MAHeroineDress();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: