设计模式-工厂方法模式扩展

时间:2022-10-02 11:59:36

对于工厂方法模式有4中扩展形式

对于这几种扩展不变的类:

Person类:

package com.feng.factory.Person;

public abstract class Person {
public abstract void getColor();
public abstract void talk();

}
WhitePerson类:

package com.feng.factory.Person;

public class WhitePerson extends Person {

@Override
public void getColor() {
// TODO Auto-generated method stub
System.out.println("我是白种人");

}

@Override
public void talk() {
// TODO Auto-generated method stub
System.out.println("白种人说话了");

}

}
BlackPerson类:

package com.feng.factory.Person;

public class BlackPerson extends Person {

@Override
public void getColor() {
// TODO Auto-generated method stub
System.out.println("我是黑种人");

}

@Override
public void talk() {
// TODO Auto-generated method stub
System.out.println("黑种人说话了");

}

}
YellowPerson类:

package com.feng.factory.Person;

public class YellowPerson extends Person {

@Override
public void getColor() {
// TODO Auto-generated method stub
System.out.println("我是黄种人");

}

@Override
public void talk() {
// TODO Auto-generated method stub
System.out.println("黄种人说话了");

}

}

(1)缩小为简单工厂模式

如果一个模块仅需要一个工厂类,那么工厂类就不需要一个接口了。直接一个工厂实现类即可,把工厂类的方法改为static方法,对于上一篇的内容修改如下:

AllPersonFactory类:

package com.feng.factory.Person;

public class AllPersonFactory {

public static <T extends Person> T create(Class<T> c) {
// TODO Auto-generated method stub
Person person = null;
try {
person = (T)Class.forName(c.getName()).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("创造人失败");
}
return (T)person;
}

}
那么测试类也需要跟着改

package com.feng.factory.Person;

public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub
Person p = AllPersonFactory.create(YellowPerson.class);
p.talk();
p.getColor();
}

}
这种模式是工厂模式的弱化,因为简单,所以又叫简单工厂模式,也叫静态工厂模式

缺点是工厂类的扩建非常困难,想想就知道了,没有一个统一的接口,如果添加一个工厂类会引起大量代码的改动
(2)升级为多个工厂
这一点其实在上一篇文章中已经用到了,就是在工厂类中不使用java的反射机制,而是为每一个人种都提供一个工厂的实现类

首先,提供一个借口:

package com.feng.factory.Person;

public interface PersonFactory {
Person create();
}
分别定义三个工厂实现这个接口

YellowPersonFactory类:

package com.feng.factory.Person;

public class YellowPersonFactory implements PersonFactory {

@Override
public Person create() {
// TODO Auto-generated method stub
return new YellowPerson();
}

}
BlackPersonFactory类:

package com.feng.factory.Person;

public class BlackPersonFactory implements PersonFactory {

@Override
public Person create() {
// TODO Auto-generated method stub
return new BlackPerson();
}

}
WhitePersonFactory类:

package com.feng.factory.Person;

public class WhitePersonFactory implements PersonFactory {

@Override
public Person create() {
// TODO Auto-generated method stub
return new WhitePerson();
}

}
测试类如下:

package com.feng.factory.Person;

public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub
PersonFactory factory = new YellowPersonFactory();
Person p = factory.create();
p.talk();
p.getColor();
}

}
这种模式职责清晰,结构简单,但是给扩展性和可维护性带来一定的影响。因为工厂类和人种类数量是相同的,维护时需要考虑两个对象之间的关系。

(3)替代单例模式
使用工厂方法模式,用过反射机制来实现单例模式

这里使用car来举例:

car类

package com.feng.factory.singleton;

public class Car {

private Car()
{

}

public void run()
{
System.out.println("车开动。。。。");
}
}
SingletonFactory类

package com.feng.factory.singleton;

import java.lang.reflect.Constructor;

public class SingletonFactory {

private static Car car;
//利用反射机制实现单例
static
{
try
{
Class c1 = Class.forName(Car.class.getName());
//获得无参的构造方法
Constructor constructor = c1.getDeclaredConstructor();
//设置无参的构造方法是可以访问的
constructor.setAccessible(true);
//产生一个实例独享
car = (Car)constructor.newInstance();
}
catch(Exception e)
{
System.out.println("获取单例失败。。。");
}
}

public static Car getInstance()
{
return car;
}


}
测试类Test:

package com.feng.factory.singleton;

public class Test {
public static void main(String[] args)
{
Car car1 = SingletonFactory.getInstance();
Car car2 = SingletonFactory.getInstance();
if(car1 == car2)
{
System.out.println("same class");
}
}

}
如果给工厂传递一个参数的话,该模式可以产生任何类的单例

(4)延迟初始化

在工厂中,对象用完之后可以不立即销毁,而是保留其初始状态,方便对象再次被用到,其实就是用一个集合类,将对象保存下来

简单模拟一个小例子:使用蚊帐开头的三个类,

工厂类AllPersonFactory

package com.feng.factory.lazy;

import java.util.HashMap;
import java.util.Map;

public class AllPersonFactory {

//缓存,用来存储对象
private static final Map<String, Person> personMap = new HashMap();
public static Person create(String type) {
Person person = null;
if(personMap.containsKey(type))
{
person = personMap.get(type);
}
else
{
if(type.equals("Yellow"))
{
person = new YellowPerson();
}
else if(type.equals("Black"))
{
person = new BlackPerson();
}
else
{
person = new WhitePerson();
}

personMap.put(type, person);
}
return person;
}

}
测试类Test

package com.feng.factory.lazy;

public class Test {

public static void main(String[] args) {
// TODO Auto-generated method stub
Person person = AllPersonFactory.create("Yellow");
Person person1 = AllPersonFactory.create("Yellow");
person.talk();
person.getColor();
if(person == person1)
{
System.out.println("same");
}

}

}

这种模式是可以扩展的,比如实现成受限的多例模式,JDBC连接池就是这种思想