public static IVector concurrentVector(IVector vector) { return new ConcurrentVector(vector);
}
// Ссылка на текущую фабрику векторов
private static VectorFactory factory = new ArrayFactory();
}
Создадим файл FactoryTest.java для проверки работы рефлексии и фабрики векторов (табл. 2).
Таблица 2 — Файл FactoryTest.java
import vectors.Vectors; import vectors.Array;
import vectors.CircularLinkedList; import vectors.CircularLinkedListFactory;
public class FactoryTest {
public static void main(String[] args) throws Exception { System.out.println("By default. ArrayFactory?: " +
(Vectors.createInstance(10) instanceof Array));
System.out.println("By default. CircularLinkedListFactory?: " + (Vectors.createInstance(10) instanceof CircularLinkedList));
Vectors.setVectorFactory(new CircularLinkedListFactory()); System.out.println("After change. ArrayFactory?: " +
(Vectors.createInstance(10) instanceof Array)); System.out.println("After change. CircularLinkedListFactory?: " +
(Vectors.createInstance(10) instanceof CircularLinkedList)); Array array = new Array(5);
array.set(0, 1); array.set(1, 2); array.set(2, 3); array.set(3, 4); array.set(4, 5);
System.out.println("Type(Array * Array) is Array?: " + (Vectors.createInstance(5, Vectors.sum(array, array)) instanceof Array));
CircularLinkedList list = new CircularLinkedList(5); list.set(0, 1);
list.set(1, 2); list.set(2, 3); list.set(3, 4); list.set(4, 5);
System.out.println("Type(List * List) is List?: " + (Vectors.createInstance(5, Vectors.sum(list, list)) instanceof CircularLinkedList));
}
}
Результат компиляции и запуска приведен на рис. 1.
Рисунок 1 — Компиляция и запуск FactoryTest.java
6
Задача: исправить код пакета векторов (интерфейс IVector и реализующие его классы) так, чтобы вектора могли использоваться в стиле foreach цикла — уже была решена ещё в работе №5. Основная схема решения говорила о следующем:
1. Нужно реализовать интерфейс Iterable<Double> классам Array и
CircularLinkedList.
2.Нужно создать классы-итераторы, реализующие интерфейс
Iterator<Double>, внутри классов Array и CircularLinkedList.
3. Нужно создать метод public java.util.Iterator iterator(); в
интерфейсе IVector и реализовать его классам Array и CircularLinkedList. Задание №4.
Добавим в классы векторов версии конструкторов, имеющие параметрами перечисленные элементы вектора (с использованием аргументов переменной длины) (табл. 3, 4).
Таблица 3 — Фрагмент измененного кода vectors/Array.java
package vectors;
import java.io.Serializable;
import java.util.NoSuchElementException; import java.util.Iterator;
import java.lang.Iterable;
public class Array implements IVector, Serializable, Iterable<Double>, Cloneable {
//Конструктор public Array(int n) {
data = new double[n];
}
//Конструктор с переменным числом параметров public Array(double... elements) {
data = new double[elements.length];
for (int i = 0; i < elements.length; ++i) { data[i] = elements[i];
}
}
//...
private final double[] data;
}
Таблица 4 — Фрагмент измененного кода vectors/CircularLinkedList.java
package vectors;
import java.io.Serializable;
import java.util.NoSuchElementException;
7
import java.util.Iterator; import java.lang.Iterable;
public class CircularLinkedList implements IVector, Serializable, Iterable<Double>, Cloneable {
// Конструктор
public CircularLinkedList(int n) {
current = head = new Node(0, null, null); head.prev = head.next = head; current_index = -1;
if (n > 0) {
Node temp = head;
for (int i = 0; i < n; ++i) {
temp = (temp.next = new Node(0, temp, null));
}
temp.next = head; head.prev = temp; size = n;
} else { size = 0;
}
}
//Конструктор с переменным числом параметров public CircularLinkedList(double... elements) {
size = elements.length;
current = head = new Node(0, null, null); head.prev = head.next = head; current_index = -1;
Node temp = head;
for (int i = 0; i < size; ++i) {
temp = (temp.next = new Node(elements[i], temp, null));
}
temp.next = head; head.prev = temp;
}
//...
private Node head, current; private int size, current_index;
}
Создадим файл VarArgsTest.java для проверки работы конструкторов с аргументами переменной длины (табл. 5).
Таблица 5 — Файл VarArgsTest.java
import vectors.Vectors; import vectors.IVector; import vectors.Array;
import vectors.CircularLinkedList; public class VarArgsTest {
public static void main(String[] args) throws Exception { Array array1 = new Array(5);
CircularLinkedList list1 = new CircularLinkedList(5); System.out.print("Array(5): "); array1.print(); System.out.print("CircularLinkedList(5): "); list1.print(); Array array2 = new Array(1.0, 2.0, 3.0);
CircularLinkedList list2 = new CircularLinkedList(1.0, 2.0); System.out.print("Array(1.0, 2.0, 3.0): "); array2.print(); System.out.print("CircularLinkedList(1.0, 2.0): "); list2.print();
}
}
Результат компиляции и запуска приведен на рис. 2. 8
Исправим метод порождения векторов в классе Vectors, использующий рефлексию, с учетом параметризованности классов Array и CircularLinkedList относительно аргументов переменной длины (табл. 6).
Таблица 6 — Фрагмент измененного кода vectors/Vectors.java
package vectors;
import java.io.IOException; import java.io.Writer; import java.io.Reader; import java.io.InputStream; import java.io.OutputStream;
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.PrintWriter; import java.io.StreamTokenizer;
import java.lang.reflect.Constructor;
public class Vectors {
//...
//Метод создания вектора фабрики векторов public static IVector createInstance(int n) {
return factory.createVector(n);
}
//Перегруженный метод создания вектора фабрики векторов public static IVector createInstance(int n, IVector vector) {
try {
double[] array = new double[n]; int vectorSize = vector.size();
n = (n < vectorSize) ? n : vectorSize; for (int i = 0; i < n; ++i) {
array[i] = vector.get(i);
}
return vector.getClass().getConstructor(double[].class).newInstance(array);
} catch (Exception e1) { try {
return vector.getClass().getConstructor(Integer.TYPE).newInstance(n);
}
catch (Exception e2) { e2.printStackTrace();
return factory.createVector(n);
}
}
}
// ...
9
// Ссылка на текущую фабрику векторов
private static VectorFactory factory = new ArrayFactory();
}
Создадим файл VarArgsExTest.java для проверки работы конструкторов с аргументами переменной длины (табл. 5).
Таблица 7 — Код VarArgsExTest.java
import vectors.Vectors; import vectors.Array;
import vectors.CircularLinkedList;
public class VarArgsExTest {
public static void main(String[] args) throws Exception { Array array1 = new Array(5);
CircularLinkedList list1 = new CircularLinkedList(5); System.out.print("Array(5): "); array1.print(); System.out.print("CircularLinkedList(5): "); list1.print(); Array array2 = new Array(1.0, 2.0, 3.0);
CircularLinkedList list2 = new CircularLinkedList(1.0, 2.0); System.out.print("Array(1.0, 2.0, 3.0): "); array2.print(); System.out.print("CircularLinkedList(1.0, 2.0): "); list2.print(); System.out.print("-----------\n");
System.out.print("Instance(4, array1): "); Vectors.createInstance(4, array1).print();
System.out.print("Instance(5, array1): "); Vectors.createInstance(5, array1).print();
System.out.print("Instance(6, array1): "); Vectors.createInstance(6, array1).print();
System.out.print("Instance(4, list1): "); Vectors.createInstance(4, list1).print();
System.out.print("Instance(5, list1): "); Vectors.createInstance(5, list1).print();
System.out.print("Instance(6, list1): "); Vectors.createInstance(6, list1).print();
System.out.print("Instance(2, array2): "); Vectors.createInstance(2, array2).print();
System.out.print("Instance(3, array2): "); Vectors.createInstance(3, array2).print();
System.out.print("Instance(4, array2): "); Vectors.createInstance(4, array2).print();
System.out.print("Instance(1, list2): "); Vectors.createInstance(1, list2).print();
System.out.print("Instance(2, list2): "); Vectors.createInstance(2, list2).print();
System.out.print("Instance(3, list2): "); Vectors.createInstance(3, list2).print();
}
}
10