定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类将实例化推迟到子类。只需要创建相关或依赖对象的家族,而不需要明确指定具体类。这样,客户程序中关于超类的代码和子类对象创建代码解耦了。
针对接口编程,而不是针对实现编程(变量不可以持有具体类的引用)。
需求:
假设我们现在有多种布局样式的 Fragment ,准备用 ViewPager 来装载, 并实现滚动切换的效果,其中会根据数据的不同采用不同的 Fragment 。
思路:
1. 创建一个 BaseFragment ,然后让所有布局样式的 Fragment 都继承这个 BaseFragm ,在要添加对象的地方直接 BaseFragment f = new Fragment1() 。 这样做功能上是可行的,但是这违背了一个设计原则,那就是尽量遵循 "针对接口编程,而不是去针对实现编程" 。
2. 采用工厂模式进行设计。这样做的好处是如果什么时候又添加了新的fragment,就可以在不改动现有的代码的情况下,可以往里面添加新的 fragment。
具体实现:
1. 创建一个工厂接口:
public abstract class BaseFragmentsInterface { FragmentInterfaces fragmentInterfaces;//fragment的引用 public Fragment getFragment(int i){ fragmentInterfaces = createFragment(i); //获取具体的fragment的实例 return fragmentInterfaces.newInstance(i); } //抽象方法,由子类来决定具体的实现,超类并不知情 protected abstract FragmentInterfaces createFragment(int i);
2. 创建具体的fragment:
public class CreateFragment1 extends BaseFragmentsInterface { //根据数据的类型的不同,创建指定的fragm @Override protected FragmentInterfaces createFragment(int i) { if(i == 0){ return new Fragment1(); }else if(i == 1){ return new Fragment1(); }else if(i == 2){ return new Fragment1(); }else if(i == 3){ return new Fragment1(); } return null; }3. 创建一个接口,让所有的fragment都实现这个接口:
public interface FragmentInterfaces { abstract Fragment newInstance(int s); }4. 创建具体的fragment:
public class Fragment1 extends BaseFragments implements FragmentInterfaces{ private String hello = "hello android"; private String defaultHello = "default value"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Bundle args = getArguments(); hello = args != null ? args.getString("hello") : defaultHello; View view = inflater.inflate(R.layout.layout_fragment1, container, false); TextView viewhello = (TextView) view.findViewById(R.id.tv); viewhello.setText(hello); return view; } //根据数据的类型不同,在fragment里面显示不同的文字说明 @Override public Fragment1 newInstance(int s) { Fragment1 newFragment = new Fragment1(); Bundle bundle = new Bundle(); if(s == 0){ bundle.putString("hello", "this is 0 fragment!"); }else if(s == 1){ bundle.putString("hello", "this is 1 fragment!"); }else if(s == 2){ bundle.putString("hello", "this is 2 fragment!"); }else if(s == 3){ bundle.putString("hello", "this is 3 fragment!"); } newFragment.setArguments(bundle); //bundle还可以在每个标签里传送数据 return newFragment; }5. 添加 fragment 到 viewpager:
//这里假设list的角标不同添加不同的fragment for (int i = 0; i < listNumber.size(); i++) { if(i >= 0 && i < 4){ BaseFragmentsInterface baseFragmentsInterface = new CreateFragment1(); fragmentList.add(baseFragmentsInterface.getFragment(i)); }else if(i >= 4 && i < 8){ BaseFragmentsInterface baseFragmentsInterface = new CreateFragment2(); fragmentList.add(baseFragmentsInterface.getFragment(i)); }else if(i >= 8 && i < 12){ BaseFragmentsInterface baseFragmentsInterface = new CreateFragment3(); fragmentList.add(baseFragmentsInterface.getFragment(i)); } }
private void initAdapter(){ viewPager.setAdapter(new MyViewPagerAdapter(getSupportFragmentManager() , fragmentList)); viewPager.setCurrentItem(0); viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
/** * 作者: on 2016/11/8 17:43 * 说明: FragmentPagerAdapter: 默认将Fragment缓存到内存 * FragmentStatePagerAdapter:切换之后就会移除其他的fragment,不会缓存到内存 */ public class MyViewPagerAdapter extends FragmentStatePagerAdapter { private Listlist; public MyViewPagerAdapter(FragmentManager fm , List list) { super(fm); this.list = list; } @Override public Fragment getItem(int position) { if(list.size() > 0){ return list.get(position); } return null; } @Override public int getCount() { return list.size(); }
6. 创建fragment 的uml: