Android开发需要掌握的设计模式——工厂模式

我们的态度是:每天进步一点点,理想终会被实现。

前言

Android中我们经常要使用的设计模式,我都会在接下来的几篇文章中为大家总结出来,比如:单例模式、观察者模式、代理模式以及包括上一篇的责任链模式等设计模式,主要讲解的方式通过理论简单例子实际项目

设计模式之工厂模式

定义

工厂模式概念?

   简单一句话:实例化对象,用工厂方法代替New方式的一种模式。
复制代码

工厂模式分为两种:

    工厂方法模式、抽象工厂模式

    工厂模式:
复制代码

    抽象工厂模式:
复制代码

工厂方法模式和抽象工厂模式区别:

  • 抽象工厂模式是工厂方法模式的扩展
  • 工厂方法模式一般只有一种类型的产品,抽象工厂模式可以有多种类型的产品。

工厂模式适用于那些场景

适用场景:

  • 具有很多同类型的对象创建
  • 不可预见创建哪种实例
  • 便于同类型扩展
  • 低耦合

简单demo

工厂方法模式:

    例如:超市有很多种类的水果:西瓜、橘子、甘蔗,我们把这些水果当成一个工厂。
复制代码

1.抽象一个水果类,创建抽象方法来获取水果单价:

public interface FruitsFactory {
   /**
    * 获取到某一类水果的价格
    */
   public void getPrice();
}
复制代码

2.让这些水果都继承水果类:


public class Peach implements FruitsFactory {
   private static final String TAG = "Peach";

   @Override
   public void getPrice() {
       //价格为5块一斤
       Log.e(TAG, "桃子的价格为" + 5 + "元一斤");
   }
}
复制代码
public class Orange implements FruitsFactory {
   private static final String TAG = "Orange";

   @Override
   public void getPrice() {
       //桃子的价格为4块一斤
       Log.e(TAG, "橘子的价格为" + "4元一斤");
   }
}
复制代码

3.创建工厂工厂类管理水果:


public class FruitsFactory {
   private static final String TAG = "FruitsFactory";
   //桃子
   public static final String PEACH = "peach";
   //橘子
   public static final String ORANGE = "orange";

   public Fruits getFruits(String type) {
       if (type.equalsIgnoreCase(PEACH)) {
           return new Peach();
       } else if (type.equalsIgnoreCase(ORANGE)) {
           return new Orange();
       } else {
           return null;
       }
   }
}
复制代码

** 3.当我们收银员去扫描水果的时候就获取价格:**


public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       FruitsFactory fruitsFactory = new FruitsFactory();
       Fruits orange = fruitsFactory.getFruits(FruitsFactory.ORANGE);
       Fruits peach = fruitsFactory.getFruits(FruitsFactory.PEACH);
       if (orange != null) {
           orange.getPrice();
       }
       if (peach != null) {
           peach.getPrice();
       }
   }
}
复制代码

运行结果:

06-14 13:39:50.712 4637-4637/com.lt.factorydemo E/Orange: 橘子的价格为4元一斤
06-14 13:39:50.712 4637-4637/com.lt.factorydemo E/Peach: 桃子的价格为5元一斤
复制代码

通过水果工厂去获取对应水果的对象,最后获得水果的价格。工厂模式就避免了创建对象,由工厂方法代替,这种方法扩展性也好,还有更多的水果只需要再工厂里面添加if else即可。

这就是我们的工厂方法模式。

需要提一点我们的工厂类里面还可以通过反射的方式获取水果对象:


public class FruitsFactory {
   private static final String TAG = "FruitsFactory";
   //桃子
   public static final String PEACH = "peach";
   public static final String PEACH_CLASS_NAME = "com.lt.factorydemo.Peach";

   //橘子
   public static final String ORANGE = "orange";
   public static final String ORANGE_CLASS_NAME = "com.lt.factorydemo.Orange";

   public Fruits getFruits(String type) {
       if (type.equalsIgnoreCase(PEACH)) {
           return new Peach();
       } else if (type.equalsIgnoreCase(ORANGE)) {
           return new Orange();
       } else {
           return null;
       }
   }

   /**
    * 通过反射获取水果对象
    * @param className
    * @return
    */
   public Fruits getFruitsByClass(String className) {
       try {
           Fruits fruits = (Fruits) Class.forName(className).newInstance();
           return fruits;
       } catch (InstantiationException e) {
           e.printStackTrace();
           return null;
       } catch (IllegalAccessException e) {
           e.printStackTrace();
           return null;
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
           return null;
       }
   }
}

复制代码

public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       FruitsFactory fruitsFactory = new FruitsFactory();
       Fruits orange = fruitsFactory.getFruitsByClass(FruitsFactory.ORANGE_CLASS_NAME);
       Fruits peach = fruitsFactory.getFruitsByClass(FruitsFactory.PEACH_CLASS_NAME);
       if (orange != null) {
           orange.getPrice();
       }
       if (peach != null) {
           peach.getPrice();
       }
   }
}
复制代码

运行结果:

06-14 14:35:24.612 6722-6722/? E/Orange: 橘子的价格为4元一斤
06-14 14:35:24.612 6722-6722/? E/Peach: 桃子的价格为5元一斤
复制代码

抽象工厂模式:

修改下场景,现在我们的很多的水果都是不一定是当季节水果,很多有可能是大棚种植,我们就将其分类为:季节水果、大棚水果

1.既然我们的水果有当季和大棚之分,我们就抽取水果种类的接口:

桃子水果

/**
* Created by Scorpio on 2018/6/14.
*
* 桃子水果
*/

public interface IPeach {
   /**
    * 获取桃子水果价格
    */
   public void getPeachPrice();
}
复制代码

橘子水果

/**
* Created by Scorpio on 2018/6/14.
* 橘子水果
*/

public interface IOrange {
   /**
    * 获取橘子水果价格
    */
   public void getOringePrice();
}
复制代码

2.创建季节水果,实现水果类

当季橘子

/**
* Created by Scorpio on 2018/6/14.
* 当季橘子
*/

public class CurrentSeasonOrange implements IOrange {
   private static final String TAG = "CurrentSeasonOrange";
   @Override
   public void getOringePrice() {
       Log.e(TAG, "当季橘子价格为4块 ");
   }
}
复制代码

大棚橘子

/**
* Created by Scorpio on 2018/6/14.
* 大棚橘子
*/

public class GreenHouseOrange implements IOrange {
   private static final String TAG = "CurrentSeasonOrange";

   @Override
   public void getOringePrice() {
       Log.e(TAG, "大棚橘子价格为8块 ");
   }
}
复制代码

当季桃子:

/**
* Created by Scorpio on 2018/6/14.
* 当季桃子
*/

public class CurrentSeasonPeach implements IPeach {
   private static final String TAG = "CurrentSeasonPeach";

   @Override
   public void getPeachPrice() {
       Log.e(TAG, "当季桃子价格为5块 ");
   }
}
复制代码

大棚桃子

/**
* Created by Scorpio on 2018/6/14.
* 大棚桃子
*/

public class GreenHousePeach implements IPeach {
   private static final String TAG = "GreenHousePeach";

   @Override
   public void getPeachPrice() {
       Log.e(TAG, "大棚桃子价格为10块 ");
   }
}
复制代码

3.创建季节工厂抽象类:

/**
* Created by Scorpio on 2018/6/14.
* 季节工厂
*/

public interface SeasonFactory {
   /**
    * 获取桃子
    *
    * @return
    */
   public IPeach getPeach();

   /**
    * 获取橘子
    *
    * @return
    */
   public IOrange getOrange();
}
复制代码

4.创建季节工厂实现类:

当季工厂:

/**
* Created by Scorpio on 2018/6/14.
* 当季工厂
*/

public class CurrenSeasonFactory implements SeasonFactory {
   @Override
   public IPeach getPeach() {
       return new CurrentSeasonPeach();
   }

   @Override
   public IOrange getOrange() {
       return new CurrentSeasonOrange();
   }
}
复制代码

大棚工厂:

/**
* Created by Scorpio on 2018/6/14.
* 大棚工厂
*/

public class GreenHouseFactory implements SeasonFactory {
   @Override
   public IPeach getPeach() {
       return new GreenHousePeach();
   }

   @Override
   public IOrange getOrange() {
       return new GreenHouseOrange();
   }
}
复制代码

5.我们的季节工厂已经创建,我们只需要去对应季节去获取对应的水果种类:

public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       //创建当季工厂对象
       SeasonFactory currenSeasonFactory = new CurrenSeasonFactory();
       //获取当季桃子
       IPeach peach = currenSeasonFactory.getPeach();
       //获取当季桃子价格
       peach.getPeachPrice();

       //获取大棚工厂
       SeasonFactory greenHouseFactory = new GreenHouseFactory();
       //获取大棚桃子
       IPeach greenHousePeach = greenHouseFactory.getPeach();
       //获取大棚桃子价格
       greenHousePeach.getPeachPrice();
   }
}
复制代码

运行结果:

06-14 15:45:03.573 9273-9273/com.lt.factorydemo E/CurrentSeasonPeach: 当季桃子价格为5块 
06-14 15:45:03.574 9273-9273/com.lt.factorydemo E/GreenHousePeach: 大棚桃子价格为10块
复制代码

这样我们一个完整的抽象工厂模式就创建好了,加入有多个季节水果、很多种类水果,只需要添加对应的实现类,然后在工厂中添加对应的水果种类即可。可扩展性非常好,低耦合。

Android项目中

现在我们当前流行的APP,一个Activity中有很多个模块,一般都是由ViewPager+Fragment来实现,那么我们的可以这些Fragment看成一个类,创建一个FragmentFactory工厂来管理。

1.创建Fragment工厂类

/**
* Created by Scorpio on 2018/6/15.
* Fragment 工厂
*/

public class FragmentFactory {
   public static final SparseArray<Fragment> mFragments = new SparseArray<>();

   public static Fragment createFragment(int position) {
       Fragment fragment = mFragments.get(position);
       if (fragment == null) {
           switch (position) {
               //首页
               case 0:
                   fragment = OneFragment.newInstance();
                   break;
               //应用
               case 1:
                   fragment = TwoFragment.newInstance();
                   break;
               //游戏
               case 2:
                   fragment = ThreeFragment.newInstance();
                   break;
               //专题
               case 3:
                   fragment = FourFragment.newInstance();
                   break;
               default:
                   break;
           }
           mFragments.put(position, fragment);
       }
       return fragment;
   }
}
复制代码

2.Activity中来获取Fragment

public class MainActivity extends AppCompatActivity {

   private ViewPager viewPager;
   private TabLayout tabLayout;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       viewPager = findViewById(R.id.vp);
       tabLayout = findViewById(R.id.tab);
       //获取标题
       String[] stringArray = getResources().getStringArray(R.array.tabs);
       //数组转list
       List<String> titles = Arrays.asList(stringArray);
       viewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(), titles));
       tabLayout.setupWithViewPager(viewPager);
   }

   class MyFragmentAdapter extends FragmentPagerAdapter {

       private List<String> mTitles;

       public MyFragmentAdapter(FragmentManager fm, List<String> mTitles) {
           super(fm);
           this.mTitles = mTitles;
       }

       @Override
       public Fragment getItem(int position) {
           return FragmentFactory.createFragment(position);
       }

       @Override
       public int getCount() {
           return mTitles.size();
       }

       @Nullable
       @Override
       public CharSequence getPageTitle(int position) {
           return mTitles.get(position);
       }
   }

}

复制代码

values的array中:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <string-array name="tabs">
       <item>首页</item>
       <item>应用</item>
       <item>游戏</item>
       <item>专题</item>
   </string-array>

</resources>
复制代码

Activity中布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.lt.factory.MainActivity">

   <android.support.design.widget.TabLayout
       android:id="@+id/tab"
       android:layout_width="match_parent"
       android:layout_height="?actionBarSize"
       app:tabMode="fixed"
       android:background="@android:color/white"
       app:tabBackground="@android:color/holo_green_light"
       app:tabSelectedTextColor="#ff4081"
       app:tabTextColor="@color/colorPrimaryDark">
   </android.support.design.widget.TabLayout>

   <android.support.v4.view.ViewPager
       android:id="@+id/vp"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:layout_marginTop="?actionBarSize">
   </android.support.v4.view.ViewPager>
</FrameLayout>
复制代码

Fragment代码:

public class OneFragment extends Fragment {


   public OneFragment() {
       // Required empty public constructor
   }

   public static OneFragment newInstance() {
       OneFragment fragment = new OneFragment();
       return fragment;
   }


   @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
       // Inflate the layout for this fragment
       return inflater.inflate(R.layout.fragment_one, container, false);
   }


}
复制代码

Fragment中布局就一个TextView。

最后运行效果:

一句话总结

工厂模式在Android中的应用还是很多的,但这都要和实际的项目结合起来使用,我们要结合需求去分析,是否适合使用工厂模式。

温馨提示: 我创建了一个技术交流群,群里有各个行业的大佬都有,大家可以在群里畅聊技术方面内容,以及文章推荐;如果有想加入的伙伴加我微信号【luotaosc】备注一下“加群” 另外关注公众号,还有一些个人收藏的视频: 回复“Android” ,获取Android视频链接。 回复“Java” ,获取Java视频链接。 回复“Python” ,获取Python视频链接等等。

原创文章不易,如果觉得写得好,扫码关注一下点个赞,是我最大的动力。

关注我,一定会有意想不到的东西等你: 每天专注分享Android干货

备注:程序圈LT

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值