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 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 titles = Arrays.asList(stringArray); viewPager.setAdapter(new MyFragmentAdapter(getSupportFragmentManager(), titles)); tabLayout.setupWithViewPager(viewPager); } class MyFragmentAdapter extends FragmentPagerAdapter { private List mTitles; public MyFragmentAdapter(FragmentManager fm, List 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中:

首頁 應用 遊戲 專題

Activity中佈局:

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中的應用還是很多的,但這都要和實際的項目結合起來使用,我們要結合需求去分析,是否適合使用工廠模式。

溫馨提示: 我創建了一個技術交流群,群裡有各個行業的大佬都有,大家可以在群裡暢聊技術方面內容,以及文章推薦;有意向加入,私信我拉你進群,還有一些個人收藏的視頻: 回覆“Android” ,獲取Android視頻鏈接。 回覆“Java” ,獲取Java視頻鏈接。 回覆“Python” ,獲取Python視頻鏈接等等。

原創文章不易,如果覺得寫得好,關注一下點個贊,是我最大的動力。

關注我,一定會有意想不到的東西等你: 每天專注分享Android乾貨