重温 Thinking in Java 6 - Registered factories

Registered factories

 

A problem with generating objects of the Pets hiearachy is the fact that every time you add a new type of Pet to the hierarchy you must remember to add it to the entries in LiteralPetCreator.java. In a system where you add more classes on a regular basis this can become problematic.

You might think of adding a static initializer to each subclass, so that the initilizer would add its class to a list somewhere. Unfortunately, static initializers are only called when the class is first loaded, so you have a chicken-and-egg problem: The generator doesn't have the class in its list, so it can never create an object of that class, so the class won't get loaded and placed in the list.

Basically, you're forced to create the list yourself, by hand (unless you want to write a tool that searches through and analyzes your source code, then creates and compiles the list). So the best you can probably do is to put the list in one central, obvious place. The base class for the hierarchy of interest is probably the best place.

The other change we'll make here is to defer the creation of the object to the class itself, using the Factory Method design patter. A factory method can be called polymorphically, and creates an object of the appropriate type for you. In this very simple version, the factory method is the create() method in the Factory interface:

 

public interface Factory<T>{
	T create();
}
 
import java.util.*;

class Part {
	public String toString(){
		return getClass().getSimpleName();
	}
	
	static List<BaseFactory<? extends Part>> partFactories = new ArrayList<BaseFactory<? extends Part>>();
	
	static {
		//Collections.addAll() gives an "unchecked generic array creation ... for varargs parameter" warning.
		partFactories.add(new FuelFilter.Factory());
		partFactories.add(new AirFilter.Factory());
		partFactories.add(new CabinAirFilter.Factory());
		partFactories.add(new OilFilter.Factory());
		partFactories.add(new FanBelt.Factory());
		partFactories.add(new PowerSteeringBelt.Factory());
		partFactories.add(new GeneratorBelt.Factory());
	}
	
	private static Random rand = new Random(47);
	
	public static Part createRandom() {
		int n = rand.nextInt(partFactories.size());
		return partFactories.get(n).create();
	}
}

class Filter extends Part{
}

class FuelFilter extends Filter {
	//Create a class Factory for each specific type:
	public static class Factory implements BaseFactory<FuelFilter>{
		public FuelFilter create(){
			return new FuelFilter();
		}
	}
}

class AirFilter extends Filter {
	public static class Factory implements BaseFactory<AirFilter>{
		public AirFilter create(){
			return new AirFilter();
		}
	}
}

class CabinAirFilter extends Filter {
	public static class Factory implements BaseFactory<CabinAirFilter> {
		public CabinAirFilter create(){
			return new CabinAirFilter();
		}
	}
}

class OilFilter extends Filter {
	public static class Factory implements BaseFactory<OilFilter> {
		public OilFilter create(){
			return new OilFilter();
		}
	}
}

class Belt extends Part{
}

class FanBelt extends Belt {
	public static class Factory implements BaseFactory<FanBelt> {
		public FanBelt create() {
			return new FanBelt();
		}
	}
}

class GeneratorBelt extends Belt {
	public static class Factory implements BaseFactory<GeneratorBelt> {
		public GeneratorBelt create(){
			return new GeneratorBelt();
		}
	}
}

class PowerSteeringBelt extends Belt {
	public static class Factory implements BaseFactory<PowerSteeringBelt> {
		public PowerSteeringBelt create(){
			return new PowerSteeringBelt();
		}
	}
}

public class RegisteredFactories {
	public static void main(String[] args){
		for(int i = 0; i < 10; i++){
			System.out.println(Part.createRandom());
		}
	}
}

/*
	Not all classes in the hierarchy should be instantiated; in this case Filter and Belt are just classified so you do not create an
	instance of either one, but only of their subclasses. If a class should be created by createRandom(), it contains an inner Factory
	class. The only way to reuse the name Factory as seen above is by qualifying BaseFactory.

	Although you can use Collections.addAll() to add the factories to the list, the compiler expresses its unhappiness with a warning
	about a "generic array creation" (which is supposed to be impossible, as you'll seen in the Generics chapter), so I reverted to
	calling add(). The createRandom() method randomly selects a factory object from partFactories and calls its create() to produce
	a new Part.
*/

 

Design Pattern - Factory

http://i8i8i8.iteye.com/admin/blogs/445941

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值