[关闭]
@linux1s1s 2019-02-18T10:10:50.000000Z 字数 5774 阅读 2701

Java设计模式 -- 适配器/装饰器模式

Java设计模式


我们先来明确一下 适配器模式有三种,分别是 类适配器模式、对象适配器模式、接口适配器模式

接下来不打算直接看这些模式的定义以及实例源码,我们直接从问题出发。

假如有如下类

  1. public class ViewController {
  2. public void getView() {
  3. System. out.println("This is Original getView() method!" );
  4. }
  5. }

现在有新的需求,需要转换这个类,如果直接修改这个类可能会带来不必要的风险,那么如何在保持该类不动的情况下转换这个类呢?

方法大体上有两种

我们不说上面两种方法有什么优缺点,先来看看如何实现

类适配器模式

定义接口抽取功能方法

  1. public interface Adapter {
  2. public void getView();
  3. public void getCount();
  4. }

接着定义继承类,一并实现该功能接口

  1. public class BaseAdapter extends ViewController implements Adapter {
  2. @Override
  3. public void getView() {
  4. super.getView();
  5. }
  6. @Override
  7. public void getCount() {
  8. System. out.println("This is Adapter extends ViewController getCount() method!");
  9. }
  10. }

然后 就可以在 测试用例中体现多态了

  1. public class TestCase {
  2. public static void main(String[] args) {
  3. /*
  4. * Call Adapter Method;
  5. */
  6. Adapter adapter = new BaseAdapter();
  7. adapter.getView();
  8. adapter.getCount();
  9. }
  10. }

上面这种解决方式就是设计模式上所说的 类适配器模式.

接下来看看第二种实现方法

对象适配器/装饰器模式

定义一个聚合类

  1. public class Wrapper implements Adapter {
  2. private ViewController source;
  3. public Wrapper( final ViewController source ) {
  4. this.source = source;
  5. }
  6. @Override
  7. public void getView() {
  8. source.getView();
  9. }
  10. @Override
  11. public void getCount() {
  12. System. out.println("This is wrapper adapter method!" );
  13. }
  14. }

构造器 需要传入ViewController 的实例

然后直接看测试用例

  1. public class TestCase {
  2. public static void main(String[] args) {
  3. /*
  4. * Call Original Method;
  5. */
  6. ViewController source = new ViewController();
  7. source.getView();
  8. /*
  9. * Call Wrapper Adapter Method;
  10. */
  11. Adapter wrapper = new Wrapper(source);
  12. wrapper.getView();
  13. wrapper.getCount();
  14. }
  15. }

这种实现思路在设计模式上叫做 对象适配器模式.

当然 我们也可以将上面的Wrapper类做如下调整

  1. public class Wrapper implements Adapter {
  2. private ViewController source;
  3. public Wrapper( final ViewController source ) {
  4. this.source = source;
  5. }
  6. @Override
  7. public void getView() {
  8. System. out.println("Before getview() method call, you can do something here before getview method");
  9. source.getView();
  10. System. out.println("After getview() method call, you can do something here after getview method");
  11. }
  12. @Override
  13. public void getCount() {
  14. System. out.println("This is wrapper adapter method!" );
  15. }
  16. }

这个时候我们也可以称之为 装饰器模式, Android中比较常见的装饰器模式是 ContextWrapper 这个类

通过上面这个例子,可能感觉到 装饰器模式和适配器模式 不是一样的吗?干嘛还弄两个设计模式?

其实 装饰模式和适配器模式都有一个别名,就是包装模式,但是这两个模式是很不一样的。适配器模式的用意是要改变所考虑对象的接口,将其转换成所需要的形式,而装饰模式的用意是保持接口,只是为了扩展功能,一个是转换,一个是扩展。

小结一下:
上面两种实现思路 迥然不同 对象适配器可以很好的解决类适配器模式中遇到的兼容问题, 他们俩孰优孰劣 还需视不同的情况区别对待。

接口适配器模式

接下来我们看一下Android中广为人知的Adapter源码:

  1. public interface Adapter {
  2. void registerDataSetObserver(DataSetObserver observer);
  3. void unregisterDataSetObserver(DataSetObserver observer);
  4. int getCount();
  5. Object getItem(int position);
  6. long getItemId( int position );
  7. boolean hasStableIds();
  8. View getView(int position, View convertView , ViewGroup parent);
  9. int getItemViewType( int position );
  10. int getViewTypeCount();
  11. boolean isEmpty();
  12. }

再看一下它的子接口

  1. public interface SpinnerAdapter extends Adapter {
  2. public View getDropDownView( int position , View convertView, ViewGroup parent);
  3. }
  4. public interface ListAdapter extends Adapter {
  5. public boolean areAllItemsEnabled();
  6. boolean isEnabled( int position );
  7. }

接着看它的实现抽象类

  1. public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
  2. private final DataSetObservable mDataSetObservable = new DataSetObservable();
  3. public boolean hasStableIds() {
  4. return false ;
  5. }
  6. public void registerDataSetObserver(DataSetObserver observer) {
  7. mDataSetObservable.registerObserver(observer );
  8. }
  9. public void unregisterDataSetObserver(DataSetObserver observer) {
  10. mDataSetObservable.unregisterObserver(observer );
  11. }
  12. /**
  13. * Notifies the attached observers that the underlying data has been changed
  14. * and any View reflecting the data set should refresh itself.
  15. */
  16. public void notifyDataSetChanged() {
  17. mDataSetObservable.notifyChanged();
  18. }
  19. /**
  20. * Notifies the attached observers that the underlying data is no longer valid
  21. * or available. Once invoked this adapter is no longer valid and should
  22. * not report further data set changes.
  23. */
  24. public void notifyDataSetInvalidated() {
  25. mDataSetObservable.notifyInvalidated();
  26. }
  27. public boolean areAllItemsEnabled() {
  28. return true ;
  29. }
  30. public boolean isEnabled(int position) {
  31. return true ;
  32. }
  33. public View getDropDownView( int position , View convertView, ViewGroup parent) {
  34. return getView(position , convertView , parent );
  35. }
  36. public int getItemViewType(int position) {
  37. return 0;
  38. }
  39. public int getViewTypeCount() {
  40. return 1;
  41. }
  42. public boolean isEmpty() {
  43. return getCount() == 0;
  44. }
  45. }

看完上面的这个BaseAdapter以后,到这我们可能不知道这个BaseAdapter类究竟有啥作用,继续往下看

  1. public class ScheduleAdapter extends BaseAdapter {
  2. @Override
  3. public int getCount() {
  4. // TODO Auto-generated method stub
  5. return 0;
  6. }
  7. @Override
  8. public Object getItem( int position ) {
  9. // TODO Auto-generated method stub
  10. return null ;
  11. }
  12. @Override
  13. public long getItemId(int position) {
  14. // TODO Auto-generated method stub
  15. return 0;
  16. }
  17. @Override
  18. public View getView( int position , View convertView, ViewGroup parent) {
  19. // TODO Auto-generated method stub
  20. return null ;
  21. }
  22. }

这么一个适配器类相信大家都不陌生,从这个类是不是就看出BaseAdapter类的好处了,如果还看不出来,最简单的办法是自己写个Adapter类 不经过BaseAdapter 就会像下面这样

  1. public class ScheduleAdapter implements ListAdapter, SpinnerAdapter {
  2. @Override
  3. public void registerDataSetObserver(DataSetObserver observer) {
  4. // TODO Auto-generated method stub
  5. }
  6. @Override
  7. public void unregisterDataSetObserver(DataSetObserver observer) {
  8. // TODO Auto-generated method stub
  9. }
  10. @Override
  11. public int getCount() {
  12. // TODO Auto-generated method stub
  13. return 0;
  14. }
  15. @Override
  16. public Object getItem( int position ) {
  17. // TODO Auto-generated method stub
  18. return null ;
  19. }
  20. @Override
  21. public long getItemId(int position) {
  22. // TODO Auto-generated method stub
  23. return 0;
  24. }
  25. @Override
  26. public boolean hasStableIds() {
  27. // TODO Auto-generated method stub
  28. return false ;
  29. }
  30. @Override
  31. public View getView( int position , View convertView, ViewGroup parent) {
  32. // TODO Auto-generated method stub
  33. return null ;
  34. }
  35. @Override
  36. public int getItemViewType(int position) {
  37. // TODO Auto-generated method stub
  38. return 0;
  39. }
  40. @Override
  41. public int getViewTypeCount() {
  42. // TODO Auto-generated method stub
  43. return 0;
  44. }
  45. @Override
  46. public boolean isEmpty() {
  47. // TODO Auto-generated method stub
  48. return false ;
  49. }
  50. @Override
  51. public View getDropDownView( int position , View convertView, ViewGroup parent) {
  52. // TODO Auto-generated method stub
  53. return null ;
  54. }
  55. @Override
  56. public boolean areAllItemsEnabled() {
  57. // TODO Auto-generated method stub
  58. return false ;
  59. }
  60. @Override
  61. public boolean isEnabled(int position) {
  62. // TODO Auto-generated method stub
  63. return false ;
  64. }
  65. }

是不是原先接口的每个方法都需要一一实现,而大部分接口方法是不需要从新实现一遍的,因此BaseAdapter这个抽象类就充当了中间适配的角色

上面这个就是设计模式中的接口适配器模式

用一张图形象的表述如下:

此处输入图片的描述

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注