1.使用Generator填充Collection
首先定义一个Generator的接口
public interface Generator<T> {
T next();
}
用适配器模式将Generator适配到Collection的构造器上,这个类使用Generator在容器中放置所需数量的对象,然后所产生的容器可以传递给任何Collection的构造器。
public class CollectionData<T> extends ArrayList<T>{
public CollectionData(Generator<T> gen, int quantity){
for (int i = 0; i < quantity; i++){
add(gen.next());
}
}
public static <T> CollectionData<T> list(Generator<T> gen, int quantity){
return new CollectionData<T>(gen, quantity);
}
}
测试,addAll()方法是所有Collection子类型的一部分,用来组装现有的Collection。
class Goverment implements Generator{
String[] foundation = ("strange women lying in ponds distributing swords" +
" is no basis for a system of government").split(" ");
private int index;
@Override
public Object next() {
return foundation[index++];
}
}
public class CollectionDataTest {
public static void main(String[] args) {
//构造器填充
Set<String> set = new LinkedHashSet<String>(new CollectionData<String>(new Goverment(), 15));
System.out.println(set);
//list填充
set.addAll(CollectionData.list(new Goverment(), 15));
System.out.println(set);
}
}
2.Map生成器
首先定义一个Pair类,因为为了组装Map,每次调用Generator的next()方法都必须产生一个“对象对”。key和value域都是public和final,为了使Pair成为只读的数据传输对象。
public class Pair<K,V> {
public final K key;
public final V value;
public Pair(K k, V v){
this.key = k;
this.value = v;
}
}
Map适配器
public class MapData<K,V> extends LinkedHashMap<K,V> {
//参数为一个单独的pair的构造器
public MapData(Generator<Pair<K,V>> gen, int quantity){
for (int i = 0; i < quantity; i++){
Pair<K,V> p = gen.next();
put(p.key,p.value);
}
}
//参数为两个不同Generator对象的构造器
public MapData(Generator<K> genK, Generator<V> genV, int quantity){
for (int i = 0; i < quantity; i++){
put(genK.next(), genV.next());
}
}
//key一个为Generator对象,value为普通对象的构造器
public MapData(Generator<K> genK, V value, int quantity){
for (int i = 0; i < quantity; i++){
put(genK.next(), value);
}
}
//key为迭代器对象,value为Generator对象
public MapData(Iterable<K> genK, Generator<V> genV){
for (K key : genK){
put(key, genV.next());
}
}
//key为迭代器对象,value为普通对象
public MapData(Iterable<K> genK, V value){
for (K key : genK){
put(key, value);
}
}
//对应的静态方法
public static <K,V> MapData<K,V> map(Generator<Pair<K,V>> gen, int quantity){
return new MapData<K, V>(gen,quantity);
}
public static <K,V> MapData<K,V> map(Generator<K> genK, Generator<V> genV, int quantity){
return new MapData<K, V>(genK,genV, quantity);
}
public static <K,V> MapData<K,V> map(Generator<K> genK, V value, int quantity){
return new MapData<K, V>(genK, value, quantity);
}
public static <K,V> MapData<K,V> map(Iterable<K> genK, Generator<V> genV){
return new MapData<K, V>(genK, genV);
}
public static <K,V> MapData<K,V> map(Iterable<K> genK, V value){
return new MapData<K, V>(genK, value);
}
}
测试类
class Letters implements Generator<Pair<Integer,String>>,Iterable<Integer>{
private int size = 9;
private int number = 1;
private char letter = 'A';
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
@Override
public boolean hasNext() {
return number < size;
}
@Override
public Integer next() {
return number++;
}
public void remove(){
throw new UnsupportedOperationException();
}
};
}
@Override
public Pair<Integer, String> next() {
return new Pair<Integer,String>(number++,"" + letter++);
}
}
public class MapDataTest {
public static void main(String[] args) {
// Pair Generator
System.out.println(MapData.map(new Letters(), 11));
//Two separate generators
System.out.println(MapData.map(new CountingGenerator.Character(),
new RandomGenerator.String(3), 8));
//a key Generator and a single value
System.out.println(MapData.map(new CountingGenerator.Character(), "Value", 6));
//An Iterable and a value Generator
System.out.println(MapData.map(new Letters(), new RandomGenerator.String(3)));
//An Iterable and a single value
System.out.println(MapData.map(new Letters(), "Pop"));
}
}
public class CountingGenerator {
public static class Boolean implements Generator<java.lang.Boolean>{
private boolean value = false;
public java.lang.Boolean next(){
value = !value;
return value;
}
}
public static class Byte implements Generator<java.lang.Byte>{
private byte value = 0;
public java.lang.Byte next(){
return value++;
}
}
static char[] chars = ("abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();
public static class Character implements Generator<java.lang.Character>{
int index = -1;
public java.lang.Character next(){
index = (index + 1) % chars.length;
return chars[index];
}
}
public static class String implements Generator<java.lang.String>{
private int length = 7;
Generator<java.lang.Character> cg = new Character();
public String(){}
public String(int length){
this.length = length;
}
public java.lang.String next(){
char[] buf = new char[length];
for (int i = 0; i < length; i++){
buf[i] = cg.next();
}
return new java.lang.String(buf);
}
public static class Short implements Generator<java.lang.Short>{
private short value = 0;
public java.lang.Short next(){
return value++;
}
}
public static class Integer implements Generator<java.lang.Integer>{
private int value = 0;
public java.lang.Integer next(){
return value++;
}
}
public static class Long implements Generator<java.lang.Long>{
private long value = 0;
public java.lang.Long next(){
return value++;
}
}
public static class Float implements Generator<java.lang.Float>{
private float value = 0;
public java.lang.Float next(){
float result = value;
value += 1.0;
return result;
}
}
public static class Double implements Generator<java.lang.Double>{
private double value = 0;
public java.lang.Double next(){
double result = value;
value += 1.0;
return result;
}
}
}
}
public class RandomGenerator {
private static Random r= new Random(47);
public static class Boolean implements Generator<java.lang.Boolean>{
public java.lang.Boolean next(){
return r.nextBoolean();
}
}
public static class Byte implements Generator<java.lang.Byte>{
public java.lang.Byte next(){
return (byte)r.nextInt();
}
}
public static class Character implements Generator<java.lang.Character>{
public java.lang.Character next(){
return CountingGenerator.chars[r.nextInt(CountingGenerator.chars.length)];
}
}
public static class String extends CountingGenerator.String{
{cg = new Character();}
public String(){}
public String(int length){super(length);}
}
public static class Integer implements Generator<java.lang.Integer>{
private int mod = 10000;
public Integer(){}
public Integer(int modulo){mod = modulo;}
public java.lang.Integer next(){
return r.nextInt();
}
}
public static class Short implements Generator<java.lang.Short>{
public java.lang.Short next(){
return (short)r.nextInt();
}
}
public static class Long implements Generator<java.lang.Long>{
private int mod = 10000;
public Long(){}
public Long(int module){mod = module;}
public java.lang.Long next(){
return new java.lang.Long(r.nextInt(mod));
}
}
public static class Float implements Generator<java.lang.Float>{
public java.lang.Float next(){
//Math.round():四舍五入
int trimmed = Math.round(r.nextFloat() * 100);
return ((float)trimmed) / 100;
}
}
public static class Double implements Generator<java.lang.Double>{
public java.lang.Double next(){
long trimmed = Math.round(r.nextDouble() * 100);
return ((double)trimmed) / 100;
}
}
}
3.使用Abstract类
享元模式:可以在普通的解决方案需要过多的对象,或者产生普通对象太多时使用享元。享元模式使得对象的一部分可以被具体化,因此,与对象中的所有事物都包含在对象内部不同,我们可以在更加高效的外部表中查找对象的一部分或整体。
下面的实例通过继承java.util.Abstract来创建定制的MapCollection。为了创建只读的Map,可以继承AbstractMap并实现entrySet()。为了创建只读的Set,可以继承AbstractSet并实现iterator()和size()。
public class Countries {
public static final String[][] DATA = {
{"ALGERIA","Algiers"}, {"ANGOLA","Luanda"}, {"BENIN","Porto-Novo"},
{"BOTSWANA","Gaberone"}, {"BURKINA FASO", "Ouagadoudou"}
};
//use AbstractMap by implementing entrySet()
private static class FlyweightMap extends AbstractMap<String,String>{
//Entry:Map中的一个对象,只存储对象的索引
private static class Entry implements Map.Entry<String,String>{
int index;
Entry(int index){ this.index = index; }
public boolean equals(Object o){
return DATA[index][0].equals(o);
}
public String getKey() { return DATA[index][0]; }
public String getValue() { return DATA[index][1]; }
public String setValue(String value) {
throw new UnsupportedOperationException();
}
public int hashCode(){
return DATA[index][0].hashCode();
}
}
//Use AbstractSet by implementing size() & iterator
//Map对象的集合
static class EntrySet extends AbstractSet<Map.Entry<String,String>>{
private int size;
EntrySet(int size){
if (size < 0)
this.size = 0;
else if (size > DATA.length)
this.size = DATA.length;
else
this.size = size;
}
public int size() { return size; }
//迭代Entry对象,迭代器只存储对象的索引
private class Iter implements Iterator<Map.Entry<String,String>>{
//Only one Entry object per Iterator
private Entry entry = new Entry(-1);
public boolean hasNext(){
return entry.index < size - 1;
}
public Map.Entry<String,String> next(){
entry.index++;
return entry;
}
public void remove(){
throw new UnsupportedOperationException();
}
}
public Iterator<Map.Entry<String,String>> iterator(){
return new Iter();
}
}
private static Set<Map.Entry<String,String>> entries = new EntrySet(DATA.length);
public Set<Map.Entry<String,String>> entrySet(){
return entries;
}
//Create a partial(局部的) map of 'size' countries
static Map<String,String> select(final int size){
return new FlyweightMap(){
public Set<Map.Entry<String,String>> entrySet(){
return new EntrySet(size);
}
};
}
static Map<String,String> map = new FlyweightMap();
public static Map<String,String> capitals(){
return map;
}
public static Map<String,String> capitals(int size){
return select(size);
}
static List<String> names= new ArrayList<String>(map.keySet());
public static List<String> names() { return names; }
public static List<String> names(int size){
return new ArrayList<String>(select(size).keySet());
}
}
}