1:程序的功能设计与分析
-:将实现deque与stack
-:采用继承与内部类来提高程序的拓展性、安全性、简洁性
-:对接到java.util.iterator中的iterator接口与iterable接口
2:程序的特点分析
-:观察到队列、栈都可以用链表进行模拟,故在设计一个链表为底层类,设计队列的接口和栈的接口,并且链表继承这两个接口,从而实现写一次代码多次使用
-:采用泛型,用于提高重新的拓展性
3:类图
4:为什么这么设计:
-:为什么设计这两个内部类?
首先要观察到list内部有两个内部类listNode与listIterator,其访问性前为static public后为private。设计前者为内部类的目的是提高代码的安全性,因为每种数据结构的节点定义都不同,所以将特定的数据结构与特定的节点绑定到一起有助于程序的可读性,且static public的内部类创建出来的实例并不会与外部类有耦合,这也进一步确保了程序的安全性。设计后者为内部类的原因是利用内部类与外部类的耦合实现多继承,因为listIterator与list并不是一个is-a的关系,所以本人不必考虑用list与iterator继承,以此来实现iterator的接口,用内部类来实现接口有助于外部类摆脱这种没必要的耦合,当然,我们并不希望外界能够访问到这一内部类,其外部与之交互的方法仅仅设置为iterator()函数,所以设计为private
-:为什么使用接口来实现deque和stack?
因为deque和stack都可以用list来实现相应的需求,所以我们考虑用接口来封装list,使之完成对应的需求,在java的标准库容器中,这样的设计也是非常常见的,对于map这种关联性的容器,我们可以封装平衡树和hash表来实现对应的需求,而且我们可以根据程序环境的不同来更改底层实现,可以拥有更好的灵活性;
-:deque与deque_ifc的关系为什么是组合关系而非继承关系?
在设计模式中,我们提倡在程序设计时要在组合和继承时选择其中一个的时,优先考虑组合关系,只有当子类必须要向上向上转型为父类的时候,才考虑用继承;
5:其他一些需要考虑的地方
-:固然使用接口封装一个容器来实现另外一种容器这种方法很高效,但这种高效仅仅限制于代码实现,在空间上,并不是特别友好,因为在一个容器实现另外一直容器时,我一定会获得一些没必要的负担,即一些功能我们用不上,但因为只是对容器的封装,我们没法对这种负担进行优化,不同容器之间的节点就是一个典型的有负担的部分;
这个时候有一个代替的方案,及对有负担的部分考虑用建筑者模式,这种设计多种模块替代有负担的部分,但这种模式可能会引发一些“不知情的错误”,比如我想用stack,但我将节点设置且deque容器的节点,这回导致一些方法运行错误;
6:源码实现:
import java.util.Iterator;
interface deque_ifc<T> {
public void pushBack(T data);
public void pushFront(T data);
public void popBack();
public void popFront();
public T getFront();
public T getBack();
public int size();
public Iterator<T> iterator();
}
interface stack_ifc<T>{
public void pushFront(T data);
public T getFront();
public void popFront();
public int size();
public Iterator<T> iterator();
}
class deque<T> implements Iterable<T>{
private deque_ifc<T> contain;
public deque(deque_ifc<T> ifc){
this.contain=ifc;
}
public void setContain(deque_ifc<T> contain){
this.contain=contain;
}
public void pushBack(T data){
this.contain.pushBack(data);
}
public void pushFront(T data){
this.contain.pushFront(data);
}
public void popBack(){
this.contain.popBack();
}
public void popFront(){
this.contain.popFront();
}
public T getFront(){
return this.contain.getFront();
}
public T getBack(){
return this.contain.getBack();
}
public int size(){
return this.contain.size();
}
public Iterator<T> iterator(){
return this.contain.iterator();
}
}
class stack<T> implements Iterable<T>{
private stack_ifc<T> contain;
public stack(stack_ifc<T> ifc){
this.contain = ifc;
}
public Iterator<T> iterator(){
return this.contain.iterator();
}
public void pop(){
this.contain.popFront();
}
public void push(T data){
this.contain.pushFront(data);
}
public int size(){
return this.contain.size();
}
}
public class list<T> implements deque_ifc<T>,Iterable<T>,stack_ifc<T>{
static public class listNode<T>{
private T data;
private listNode<T> next;
private listNode<T> front;
public void setNext(listNode<T> next){
this.next=next;
}
public listNode<T> getNext(){
return this.next;
}
public void setData(T newData){
this.data=newData;
}
public T getData(){
return data;
}
public listNode(T data){
this.data=data;
}
public listNode(){}
}
private class listIterator implements Iterator<T>{//
private listNode<T> iteratorPointer;
listIterator(){
iteratorPointer=head;
}
@Override
public boolean hasNext() {
return iteratorPointer.next != tail && iteratorPointer != null;
}
@Override
public T next() {
iteratorPointer=iteratorPointer.next;
return iteratorPointer.data;
}
}
public void pushFront(T data){
listNode<T> newNode=new listNode<T>(data);
listNode<T> first = head.next;
head.next = newNode;
newNode.front = head;
first.front = newNode;
newNode.next = first;
size++;
}
public void pushBack(T data){
listNode<T> newNode = new listNode<T>(data);
listNode<T> back = tail.front;
tail.front=newNode;
newNode.next=tail;
back.next=newNode;
newNode.front=newNode;
size++;
}
public void popBack() {
listNode<T> node = tail.front.front;
tail.front = node;
node.next = tail;
size--;
}
public void popFront() {
listNode<T> node = head.next.next;
head.next = node;
node.front = head;
size--;
}
public Iterator<T> iterator(){
return new listIterator();
}
public listNode<T> begin() {
return head.next;
}
public listNode<T> end() {
return tail;
}
public int size() {
return size;
}
@Override
public T getFront() {
if(size!=0) return head.next.data;
return null;
}
@Override
public T getBack() {
if(size!=0) return tail.front.data;
return null;
}
list() {
head = new listNode<T>();
tail = new listNode<T>();
head.next = tail;
tail.front = head;
}
private listNode<T> head, tail;
private int size;
@FunctionalInterface
private interface noPara{
void test();
}
static public void main(String[] None){
deque<Integer> que = new deque<Integer>(new list<Integer>());
for (int i = 0; i < 10; i++) {
que.pushBack(i);
}
System.out.println("deque iterator");
for (Iterator<Integer> t = que.iterator(); t.hasNext();) {
Integer data = t.next();
System.out.printf("%d ", data);
}
System.out.println();
System.out.println("deque iterable");
for (Integer t : que) {
System.out.printf("%d ", t);
}
System.out.println();
stack<Integer> stack_int = new stack<Integer>(new list<Integer>());
for (int i = 0; i < 10; i++) {
stack_int.push(i);
}
System.out.println("stack iterator");
for (Iterator<Integer> t = stack_int.iterator(); t.hasNext();) {
Integer data = t.next();
System.out.printf("%d ", data);
}
System.out.println();
System.out.println("stack iterator");
for (Integer t : stack_int) {
System.out.printf("%d ", t);
}
}
}