寻找android中的设计模式(三)



寻找android中的设计模式(三)



  1. 寻找工厂模式

    工厂模式的家族分四种:静态工厂模式、简单工厂模式、工厂方法模式、抽象工厂模式。

    下面以开冒菜店为例,假设我定义了一家冒菜店:

    	<pre class="java" name="code">public class MaoCaiStore {
    	
    	public MaoCai sellMaoCai(String type) {
    		MaoCai maoCai = null;
    		if (type.equals("weila")) {
    			maoCai = new WeilaMaoCai();
    		} else if (type.equals("zhongla")) {
    			maoCai = new ZhonglaMaoCai();
    		} else if (type.equals("mala")) {
    			maoCai = new MalaMaoCai();
    		} else {
    			maoCai = new ZhonglaMaoCai();
    		}
    		maoCai.prepare();
    		maoCai.fire();
    		maoCai.addTiaoliao();
    		return maoCai;
    	}
    }

     

    可以看到,在sellMaoCai方法里面会根据传入参数不同而做不同口味的冒菜。这样就违背了OO原则(单一原则,开闭原则等)如果增加一种口味的冒菜,就得修改里面的代码。看下静态工厂模式的处理方式:

    public class StaticMaoCaiFactory {
    	public static MaoCai createMaoCai(String type){
    		MaoCai maoCai = null;
    		if (type.equals("weila")) {
    			maoCai = new WeilaMaoCai();
    		} else if (type.equals("zhongla")) {
    			maoCai = new ZhonglaMaoCai();
    		} else if (type.equals("mala")) {
    			maoCai = new MalaMaoCai();
    		} else {
    			maoCai = new ZhonglaMaoCai();
    		}
    		return maoCai;
    	}
    }
    public  class MaoCaiStore {
    	
    	public MaoCai sellMaoCai(String type) {
    		MaoCai maoCai = StaticMaoCaiFactory.createMaoCai(type);
    		maoCai.prepare();
    		maoCai.fire();
    		maoCai.addTiaoliao();
    		return maoCai;
    	}
    }

    可以看到比较简单,只是将创建冒菜的工作交给了StaticMaoCaiFactory中的静态方法。这样的好处是增加一种口味的冒菜只要修改StaticMaoCaiFactory中的静态方法即可,将冒菜店和创建冒菜隔离,冒菜店只负责拿到冒菜开始做就行,至于冒菜的来源不关心。

    下面看下简单工厂模式是如何做的:

    public class SampleMaoCaiFactory {
    	public MaoCai createMaoCai(String type){
    		MaoCai maoCai = null;
    		if (type.equals("weila")) {
    			maoCai = new WeilaMaoCai();
    		} else if (type.equals("zhongla")) {
    			maoCai = new ZhonglaMaoCai();
    		} else if (type.equals("mala")) {
    			maoCai = new MalaMaoCai();
    		} else {
    			maoCai = new ZhonglaMaoCai();
    		}
    		return maoCai;
    	}
    }
    public  class MaoCaiStore {
    	private SampleMaoCaiFactory mSampleMaoCaiFactory;
    	public MaoCaiStore() {
    		mSampleMaoCaiFactory = new SampleMaoCaiFactory();
    	}
    	public MaoCai sellMaoCai(String type) {
    		MaoCai maoCai = mSampleMaoCaiFactory.createMaoCai(type);
    		maoCai.prepare();
    		maoCai.fire();
    		maoCai.addTiaoliao();
    		return maoCai;
    	}
    }

    可以看出createMaoCai不在是一个静态方法,而是需要创建工厂对象才能调用。好处跟静态工厂模式一样,只不过这里用组合的方式把工厂组合进来。

    下面看下工厂方法模式:

    定义:定义一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式把类实例化的过程推迟到子类。

    意思就是把创建冒菜的任务交给冒菜店的子类(各个分店:上海西安),如下:

    public abstract class MaoCaiStore {
    	public abstract MaoCai createMaoCai(String type);
    	
    	public MaoCai sellMaoCai(String type) {
    		MaoCai maoCai = createMaoCai(type);
    		maoCai.prepare();
    		maoCai.fire();
    		maoCai.addTiaoliao();
    		return maoCai;
    	}
    }
    public class ShanghaiMaoCaiStore extends MaoCaiStore {
    	
    	@Override
    	public MaoCai createMaoCai(String type) {
    		MaoCai maoCai = null;
    		if (type.equals("weila")) {
    			maoCai = new ShanghaiWeilaMaoCai();
    		} else if (type.equals("zhongla")) {
    			maoCai = new ShanghaiZhonglaMaoCai();
    		} else if (type.equals("mala")) {
    			maoCai = new ShanghaiMalaMaoCai();
    		} else {
    			maoCai = new ShanghaiZhonglaMaoCai();
    		}
    		return maoCai;
    	}
    
    }
    public class XianMaoCaiStore extends MaoCaiStore {
    
    	@Override
    	public MaoCai createMaoCai(String type) {
    		MaoCai maoCai = null;
    		if (type.equals("weila")) {
    			maoCai = new XianWeilaMaoCai();
    		} else if (type.equals("zhongla")) {
    			maoCai = new XianZhonglaMaoCai();
    		} else if (type.equals("mala")) {
    			maoCai = new XianMalaMaoCai();
    		} else {
    			maoCai = new XianZhonglaMaoCai();
    		}
    		return maoCai;
    	}
    
    }

    可以看到,上海分店的工厂专门制造上海口味的冒菜,西安分店的工厂专门制造西安口味的冒菜。再看下定义:定义一个创建对象的接口就是,这个方法:

    public abstract MaoCai createMaoCai(String type);

  最后看下,抽象工厂方法:


定义:提供一个接口,用于创建相关的或依赖对象的家族,而不需要明确指定具体类。


比如冒菜店提供的各种蔬菜和肉类必须由当地提供,上海得由上海原料工厂提供,西安得由西安原料工厂提供。


下面定义一个接口用来获取蔬菜和肉:

public interface MaoCaiYuanliaoFactory {
	public void createShuCai();
	public void createRou();
}


上海原料工厂:

public class ShanghaiMaoCaiYuanliaoFactory implements MaoCaiYuanliaoFactory {

	@Override
	public void createShuCai() {
		System.out.println("获取上海产的蔬菜");
	}

	@Override
	public void createRou() {
		System.out.println("获取上海产的蔬菜");
	}

}


西安原料工厂:

public class XiAnMaoCaiYuanliaoFactory implements MaoCaiYuanliaoFactory {

	@Override
	public void createShuCai() {
		System.out.println("获取西安产的蔬菜");
	}

	@Override
	public void createRou() {
		System.out.println("获取西安产的肉");
	}

}

然后在各分店冒菜店里面组合该冒菜原料工厂:

public class ShanghaiMaoCaiStore extends MaoCaiStore {
	private MaoCaiYuanliaoFactory maoCaiYuanliaoFactory = new ShanghaiMaoCaiYuanliaoFactory();

下面测试下,比如在上海冒菜店卖一份麻辣的冒菜:

	public static void main(String[] args) {
		ShanghaiMaoCaiStore shanghaiMaoCaiStore = new ShanghaiMaoCaiStore();
		shanghaiMaoCaiStore.sellMaoCai("mala");
	}

打印结果:

准备
获取上海产的蔬菜
获取上海产的蔬菜
开抄
加调料


下面寻找下android源码当中是如何使用工厂模式的:


    1. BitmapFactory中有很多创建位图的静态方法:(静态工厂模式)

      public static Bitmap decodeFile(String pathName, Options opts) {
      public static Bitmap decodeResource(Resources res, int id, Options opts) {

    2. 原生联系人应用里面很多fragment里面都有createListAdapter方法:(工厂方法模式)

      根据定义找到创建对象的接口:(父类ContactEntryListFragment里面)

      protected abstract T createListAdapter();
      mAdapter = createListAdapter();
      找到子类的实现:

          @Override
          protected ContactListAdapter createListAdapter() {
              DefaultContactListAdapter adapter = new DefaultContactListAdapter(getContext());
              adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
              adapter.setDisplayPhotos(true);
              adapter.setPhotoPosition(
                      ContactListItemView.getDefaultPhotoPosition(/* opposite = */ false));
              return adapter;
          }
          @Override
          public JoinContactListAdapter createListAdapter() {
              JoinContactListAdapter adapter = new JoinContactListAdapter(getActivity());
              adapter.setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(true /* opposite */));
              return adapter;
          }

      可以看到子类都实现了该接口来创建需要的适配器。

    3. 电话所有者与联系人之间的交互。(抽象工厂模式)

      根据定义找到接口定义:

      /**
       * Represents a default interaction between the phone's owner and a contact
       */
      public interface ContactInteraction {
          Intent getIntent();
          long getInteractionDate();
          String getViewHeader(Context context);
          String getViewBody(Context context);
          String getViewFooter(Context context);
          Drawable getIcon(Context context);
          Drawable getBodyIcon(Context context);
          Drawable getFooterIcon(Context context);
          String getContentDescription(Context context);
          /** The resource id for the icon, if available. May be 0 if one is not available. */
          int getIconResourceId();
      }

      可以看到这么多接口用来创建跟联系人相关的产品。具体创建哪些对象在实现类里面提供。

      一般跟联系人的交互有通话、短信、日历活动。如下:

      public class CalendarInteraction implements ContactInteraction {
      public class CallLogInteraction implements ContactInteraction {
      public class SmsInteraction implements ContactInteraction {

      上面三个实现类里面实现了各种产品的创建,可以看到抽象工厂可以让制造的相关产品组合起来。而且具体的实现类里面用了工厂方法来创建产品。比如:

      CallLogInteraction中实现了图标的创建:

          public Drawable getIcon(Context context) {
              return context.getResources().getDrawable(CALL_LOG_ICON_RES);
          }

      其他SmsInteractionCalendarInteraction也都创建了图标。

  1. 总结

    学完了工厂模式后,下面总结下目前涉及OO原则:

    1. 封装变化

    2. 多用组合,少用继承

    3. 针对接口编程,不针对实现编程

    4. 为交互对象之间的松耦合设计而努力

    5. 类应该对扩展开发,对修改关闭

    6. 依赖抽象,不要依赖具体类



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值