装饰者模式是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,便可以使用上面的方法来进行实现