Java设计模式-装饰者模式

Java设计模式-装饰者模式

装饰者模式是什么

装饰者模式是23中设计模式的一种。
从这个模式的名字“装饰者”可以看出,这个设计模式是基于已有的类进行设计的一种模式。
装饰者模式他是为了让已经存在的类的功能更多,更全面。

装饰者模式怎么用

首先我们先放入我们的测试类,测试类中的类便是用装饰者模式写的

public class ListMaxTest {
	 public static void main(String[] args) {
		 List<Integer> list=new LowListMax<Integer>(new ArrayList<Integer>(), 10);
		 for(int i=0;i<100;i++)
		 {
			 System.err.println(i);
			 list.add(i);
		 }
	 }
 }

下面是执行结果

0
1
2
3
4
5
6
7
8
9
10
Exception in thread "main" java.lang.RuntimeException: 添加此	参数后,长度会超出
at com.jun.decorator.LowListMax.add(LowListMax.java:21)
at com.jun.decorator.ListMaxTest.main(ListMaxTest.java:12)

当list准备添加第11个参数的时候,就报错了,所以new LowListMax(new ArrayList(), 10);中的10便是这个list的最大参数,接下来我们来看看这个类是怎么实现的。

public class  LowListMax  <T> implements List<T>{
	private final List<T> list;
	private final int max;
	public LowListMax(List<T> list,int max)
	{
		this.list=list;
		this.max=max;
	}
	@Override
	public boolean add(T arg0) {
		if(list.size()<max) {
			this.list.add(arg0);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
		return true;
	}
	@Override
	public void add(int arg0, T arg1) {
		if(list.size()<max) {
			this.list.add(arg0,arg1);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
	}
	@Override
	public boolean addAll(Collection<? extends T> arg0) {
		if(list.size()<max) {
			this.list.addAll(arg0);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
		return true;
	}
	@Override
	public boolean addAll(int arg0, Collection<? extends T> arg1) {
		if(list.size()<max) {
			this.list.addAll(arg0,arg1);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
		return true;
	}
	@Override
	public void clear() {
		list.clear();
	}
	@Override
	public boolean contains(Object arg0) {
		return list.contains(arg0);
	}
	@Override
	public boolean containsAll(Collection<?> arg0) {
		return list.containsAll(arg0);
	}
	@Override
	public T get(int arg0) {
		return list.get(arg0);
	}
	@Override
	public int indexOf(Object arg0) {
		return list.indexOf(arg0);
	}
	@Override
	public boolean isEmpty() {
		return list.isEmpty();
	}
	@Override
	public Iterator<T> iterator() {
		return list.iterator();
	}
	@Override
	public int lastIndexOf(Object arg0) {
		return list.lastIndexOf(arg0);
	}
	@Override
	public ListIterator<T> listIterator() {
		return list.listIterator();
	}
	@Override
	public ListIterator<T> listIterator(int arg0) {
		return list.listIterator(arg0);
	}
	@Override
	public boolean remove(Object arg0) {
		return list.remove(arg0);
	}
	@Override
	public T remove(int arg0) {
		return list.remove(arg0);
	}
	@Override
	public boolean removeAll(Collection<?> arg0) {
		return list.removeAll(arg0);
	}
	@Override
	public boolean retainAll(Collection<?> arg0) {
		return list.retainAll(arg0);
	}
	@Override
	public T set(int arg0, T arg1) {
		return list.set(arg0, arg1);
	}
	@Override
	public int size() {
		return list.size();
	}
	@Override
	public List<T> subList(int arg0, int arg1) {
		return list.subList(arg0, arg1);
	}
	@Override
	public Object[] toArray() {
		return list.toArray();
	}
	@Override
	public <T> T[] toArray(T[] arg0) {
		return list.toArray(arg0);
	}
}

我们可以看到,这个类继承了List接口,并且实现了接口中的所有方法,但他实现的方法中并没有进行任何处理,只是加了一个长度判断,实际添加的还是new ArrayList.
从这个new ArrayList中体现了装饰者模式的强大,他不仅能扩展被装饰的类,还能保留被装饰的类的独特性。
如:ArrayList 的优点就是遍历快,那么new LowListMax(new ArrayList(), 10);将继承遍历快的优点。
LinkedList是删除插入快,所以如果我们经常删除插入数据的话只需要将
new LowListMax(new ArrayList(), 10);改成
new LowListMax(new LinkedList(), 10);
就会继承List的删除插入快的优点。

从这个类的名字来看LowListMax Low,就是低等的
其实这个类存在一个bug

public class ListMaxTest {
	 public static void main(String[] args) {
		 List<Integer> list=new LowListMax<Integer>(new ArrayList<Integer>(), 10);
		 ListIterator<Integer> iterator=list.listIterator();
		 for(int i=0;i<100;i++)
		 {
			 System.err.println(i);
			// list.add(i);
			 iterator.add(i);
		 }
	 }
 }

如果我们使用listIterator来添加,那么他将不受上面的限制,将可以无限添加
这是他的输出结果

0
1
2
3
4
5
6
7
8
9
10
11
12
13
...
后面还有,太长了

从中我们可以看到,13明显已经超过了10,那我们能不能解决了,当然能,下面我们来看高配版的运行结果

public class ListMaxTest {
	 public static void main(String[] args) {
		 List<Integer> list=new ListMax<Integer>(new ArrayList<Integer>(), 10);
		 ListIterator<Integer> iterator=list.listIterator();
		 for(int i=0;i<100;i++)
		 {
			 System.err.println(i);
			// list.add(i);
			 iterator.add(i);
		 }
	 }
 }
0
1
2
3
4
5
6
7
8
9
10
Exception in thread "main" java.lang.RuntimeException: 长度超过最大限制
	at com.jun.decorator.IteratorMax.add(IteratorMax.java:23)
	at com.jun.decorator.ListMaxTest.main(ListMaxTest.java:15)

高配版中,当添加第11个的时候就会报错 长度超过最大限制
我们只是换了一个对象new,便做到无漏洞,我们来看看具体是怎么实现的了

public class  ListMax  <T> implements List<T>{
	private final List<T> list;
	private final int max;
	public ListMax(List<T> list,int max)
	{
		this.list=list;
		this.max=max;
	}
	@Override
	public boolean add(T arg0) {
		if(list.size()<max) {
			this.list.add(arg0);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
		return true;
	}
	@Override
	public void add(int arg0, T arg1) {
		if(list.size()<max) {
			this.list.add(arg0,arg1);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
	}
	@Override
	public boolean addAll(Collection<? extends T> arg0) {
		if(list.size()<max) {
			this.list.addAll(arg0);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
		return true;
	}
	@Override
	public boolean addAll(int arg0, Collection<? extends T> arg1) {
		if(list.size()<max) {
			this.list.addAll(arg0,arg1);
		}else {
			throw new RuntimeException("添加此参数后,长度会超出");
		}
		return true;
	}
	@Override
	public void clear() {
		list.clear();
	}
	@Override
	public boolean contains(Object arg0) {
		return list.contains(arg0);
	}
	@Override
	public boolean containsAll(Collection<?> arg0) {
		return list.containsAll(arg0);
	}
	@Override
	public T get(int arg0) {
		return list.get(arg0);
	}
	@Override
	public int indexOf(Object arg0) {
		return list.indexOf(arg0);
	}
	@Override
	public boolean isEmpty() {
		return list.isEmpty();
	}
	@Override
	public Iterator<T> iterator() {
		return list.iterator();
	}
	@Override
	public int lastIndexOf(Object arg0) {
		return list.lastIndexOf(arg0);
	}
	@Override
	public ListIterator<T> listIterator() {
		return new IteratorMax<>(list.listIterator(), max);
	}
	@Override
	public ListIterator<T> listIterator(int arg0) {
		return new IteratorMax<>(list.listIterator(arg0), max);
	}
	@Override
	public boolean remove(Object arg0) {
		return list.remove(arg0);
	}
	@Override
	public T remove(int arg0) {
		return list.remove(arg0);
	}
	@Override
	public boolean removeAll(Collection<?> arg0) {
		return list.removeAll(arg0);
	}
	@Override
	public boolean retainAll(Collection<?> arg0) {
		return list.retainAll(arg0);
	}
	@Override
	public T set(int arg0, T arg1) {
		return list.set(arg0, arg1);
	}
	@Override
	public int size() {
		return list.size();
	}
	@Override
	public List<T> subList(int arg0, int arg1) {
		return list.subList(arg0, arg1);
	}
	@Override
	public Object[] toArray() {
		return list.toArray();
	}
	@Override
	public <T> T[] toArray(T[] arg0) {
		return list.toArray(arg0);
	}
}

我们可以清晰的看到,lowListMax和ListMax的差异只存在

@Override
public ListIterator listIterator() {
	return new IteratorMax<>(list.listIterator(), max);
}
@Override
public ListIterator listIterator(int arg0) {
	return new IteratorMax<>(list.listIterator(arg0), max);
}

哦,原来如此,这里也用到了装饰者模式
那我们来看看这个装饰者模式是怎么实现的

public class IteratorMax<E> implements ListIterator<E> {
private final ListIterator<E> listIterator;
private final int max;
public IteratorMax(Iterator<E> iterator,int max)
{
	this.listIterator=(ListIterator<E>) iterator;
	this.max=max;
}
	public int size(){
		return listIterator.nextIndex();
	}
	
	public void add(E arg0) {
		if(this.size()<max){
			listIterator.add(arg0);
		}else{
			throw new RuntimeException("长度超过最大限制");
		}
	}

	public boolean hasNext() {
		return listIterator.hasNext();
	}

	public boolean hasPrevious() {
		return listIterator.hasPrevious();
	}

	public E next() {
		return listIterator.next();
	}

	public int nextIndex() {
		return listIterator.nextIndex();
	}

	public E previous() {
		return listIterator.previous();
	}

	public int previousIndex() {
		return listIterator.previousIndex();
	}

	public void remove() {
		listIterator.remove();
	}

	public void set(E arg0) {
		if(this.size()<max){
			listIterator.set(arg0);
		}else{
			throw new RuntimeException("长度超过最大限制");
		}
	}
}

原来如此,只是在装饰的maxList类中使用了IteratorMax来装饰ListIterator,被装饰后,我们也能控制ListIterator的长度大小,这就是装饰者模式的使用

装饰者模式在什么时候使用

装饰者模式的使用往往都是对已经实现的类操作,想在实现的类中添加一些限制,但不覆盖已有的实现。
如我们想实现一个长度限制的list,便可以使用上面的方法来进行实现

你可能感兴趣的:(设计模式,java,设计模式,java,后端,抽象代数,数据结构)