Android開發需要掌握的設計模式——工廠模式

我們的態度是:每天進步一點點,理想終會被實現。

前言

Android中我們經常要使用的設計模式,我都會在接下來的幾篇文章中為大家總結出來,比如:單例模式、觀察者模式、代理模式以及包括上一篇的責任鏈模式等設計模式,主要講解的方式通過理論簡單例子實際項目

設計模式之工廠模式

定義

工廠模式概念?

 簡單一句話:實例化對象,用工廠方法代替New方式的一種模式。

工廠模式分為兩種:

 工廠方法模式、抽象工廠模式
 工廠模式:
Android開發需要掌握的設計模式——工廠模式

 抽象工廠模式:
Android開發需要掌握的設計模式——工廠模式

工廠方法模式和抽象工廠模式區別:

  • 抽象工廠模式是工廠方法模式的擴展
  • 工廠方法模式一般只有一種類型的產品,抽象工廠模式可以有多種類型的產品。

工廠模式適用於那些場景

適用場景:

  • 具有很多同類型的對象創建
  • 不可預見創建哪種實例
  • 便於同類型擴展
  • 低耦合

簡單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” ,獲取Android視頻鏈接。 回覆“Java” ,獲取Java視頻鏈接。 回覆“Python” ,獲取Python視頻鏈接等等。

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

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


分享到:


相關文章: