標(biāo)簽(空格分隔): 設(shè)計(jì)模式
前言
Strategy(策略)設(shè)計(jì)模式是設(shè)計(jì)架構(gòu)時(shí)候常用到的設(shè)計(jì)模式之一。我們開發(fā)中常常遇到這樣的情況:在實(shí)現(xiàn)某一個(gè)功能的時(shí)候,根據(jù)不同的環(huán)境和情況實(shí)現(xiàn)不同的算法和規(guī)則(比如排序功能)补箍。很多人解決的方案就是用if else代替,if(xx)就用a排序方案压昼,if(yy)就用b排序方案送滞,else....。功能的確能實(shí)現(xiàn)朽褪, 但是以后擴(kuò)展和維護(hù)起來相當(dāng)不容易置吓。遇到這樣的情況(在實(shí)現(xiàn)某一個(gè)功能的時(shí)候,根據(jù)不同的環(huán)境和情況實(shí)現(xiàn)不同的算法和規(guī)則)缔赠,我們可以嘗試用策略設(shè)計(jì)模式來解決這樣的問題衍锚。
場(chǎng)景1.對(duì)一組[1,2,6,4,3,2]進(jìn)行排序,會(huì)怎么寫嗤堰?
- 程序設(shè)計(jì)1
public class MainActivity extends Activity{
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv_content);
//數(shù)組創(chuàng)建
Integer a[] = {1,2,6,4,3,2};
//數(shù)組排序
DataSorter.sort(a);
//數(shù)組輸出到界面
tv.setText(toStringArray(a));
}
/**
* 把數(shù)組轉(zhuǎn)成一段字符串輸出到界面
* @param a
* @return 一段排好序的字符串
*/
public String toStringArray(Integer[] a) {
String str = "";
for(int i=0; i<a.length; i++) {
str += a[i].toString() + ",";
}
return str;
}
}
/**
* Created by liangjunjie on 16/6/16.
* 排序工具
*/
public class DataSorter {
public static void sort(int[] a) {
for(int i=a.length; i>0; i--) {
for(int j=0; j<i-1; j++) {
if(a[j] > a[j+1]) {
swap(a, j , j+1);
}
}
}
}
private static void swap(int[] a, int x, int y) {
int temp = a[x];
a[x] = a[y];
a[y] = temp;
}
}
排序算法:
結(jié)果:
場(chǎng)景2.加入現(xiàn)在我要排序的不是一組 數(shù)字了戴质,是要對(duì)一組 貓按照體重來排序。
- 程序設(shè)計(jì)2
public class MainActivity extends Activity{
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv_content);
//數(shù)組創(chuàng)建
Cat kitty = new Cat("kitty", 3);//kitty,3kg置森,1year
Cat tony = new Cat("tony", 6);//tony斗埂, 5kg, 2year
Cat himit = new Cat("himit", 6);//himt, 6kg 3year
Cat a[] = {kitty, tony, himit};
//數(shù)組排序
DataSorter.sort(a);
//數(shù)組輸出到界面
tv.setText(toStringArray(a));
}
/**
* 把數(shù)組轉(zhuǎn)成一段字符串輸出到界面
* @param a
* @return 一段排好序的字符串
*/
public String toStringArray(Cat[] a) {
String str = "";
for(int i=0; i<a.length; i++) {
str += a[i].toString() + ",";
}
return str;
}
}
public class Cat {
public Cat(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String name;
public int weight;
@Override
public String toString() {
return "name-" + name + " weight-" + weight;
}
}
/**
* Created by liangjunjie on 16/6/16.
* 排序工具
*/
public class DataSorter {
public static void sort(Cat[] a) {
for(int i=a.length; i>0; i--) {
for(int j=0; j<i-1; j++) {
if(((Cat)a[j]).weight > ((Cat)a[j+1]).weight) {
swap(a, j , j+1);
}
}
}
}
private static void swap(Cat[] a, Integer x, Integer y) {
Cat temp = a[x];
a[x] = a[y];
a[y] = temp;
}
}
結(jié)果:
功能的確實(shí)現(xiàn)了凫海。
但出現(xiàn)缺點(diǎn):
1.要修改更換排序的東西呛凶,就必須修改 DataSort 類,違背了設(shè)計(jì)原則的:《開閉原則》 - 對(duì)擴(kuò)展開放行贪,對(duì)修改關(guān)閉漾稀。
2.也是違背了設(shè)計(jì)原則中的:《依賴倒置原則》 - 高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象建瘫。就是說崭捍,類 DataSort依賴了 Cat 類,如果以后要對(duì) Dog 排序啰脚,那么就必須修改 DataSort 的類殷蛇,更改依賴對(duì)象把 Cat 改為 Dog。
場(chǎng)景3.現(xiàn)在我需要對(duì)貓的名字的長(zhǎng)度進(jìn)行排序橄浓,就是 實(shí)現(xiàn)結(jié)果為:(himit2 ,kitty, tony),要求設(shè)計(jì)成更下次改回對(duì)貓的體重修改的時(shí)候粒梦,要能改 DataSort修改。
- 程序設(shè)計(jì)3
//main 不用動(dòng)
public class MainActivity extends Activity{
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv_content);
//數(shù)組創(chuàng)建
Cat kitty = new Cat("kitty", 3);//kitty荸实,3kg匀们,1year
Cat tony = new Cat("tony", 6);//tony, 5kg准给, 2year
Cat himit = new Cat("himit", 6);//himt, 6kg 3year
Cat a[] = {kitty, tony, himit};
//數(shù)組排序
DataSorter.sort(a);
//數(shù)組輸出到界面
tv.setText(toStringArray(a));
}
/**
* 把數(shù)組轉(zhuǎn)成一段字符串輸出到界面
* @param a
* @return 一段排好序的字符串
*/
public String toStringArray(Cat[] a) {
String str = "";
for(int i=0; i<a.length; i++) {
str += a[i].toString() + ",";
}
return str;
}
}
/**
* Created by liangjunjie on 16/6/16.
* 增加一個(gè) Comparable接口
*/
public interface Comparable<T> {
int compareTo(T o);
}
/**
* Created by liangjunjie on 16/6/16.
* 排序工具
* DataSort 不在依賴 Cat 了泄朴,改為依賴接口(抽象)Comparable。
*/
public class DataSorter {
public static void sort(Comparable[] a) {
for(int i=a.length; i>0; i--) {
for(int j=0; j<i-1; j++) {
Comparable o1 = a[j];
Comparable o2 = a[j+1];
if(o1.compareTo(o2) == 1) {
swap(a, j , j+1);
}
}
}
}
private static void swap(Comparable[] a, int x, int y) {
Comparable temp = a[x];
a[x] = a[y];
a[y] = temp;
}
}
/**
* Created by liangjunjie on 16/6/16.
* cat 實(shí)現(xiàn)接口 Comparable
*/
public class Cat implements Comparable<Cat>{
public Cat(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String name;
public int weight;
@Override
public String toString() {
return "name-" + name + " weight-" + weight;
}
@Override
public int compareTo(Cat o) {
if(this.name.length() > o.name.length()) {
return 1;
} else if(this.name.length() < o.name.length()) {
return -1;
} else {
return 0;
}
}
}
結(jié)果:
改到到這里露氮,你會(huì)發(fā)現(xiàn)這樣的更改祖灰,以后更排序方式,不要對(duì) cat 的名字長(zhǎng)度排序畔规,而是改回之前對(duì)體重進(jìn)行排序夫植,DataSort 真的不用進(jìn)行修改,只要對(duì) Cat 類的 compareTo(Cat o) 方法進(jìn)行一下修改油讯,就可以回到按體重排序。
/**
* Created by liangjunjie on 16/6/16.
*/
public class Cat implements Comparable<Cat>{
public Cat(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String name;
public int weight;
@Override
public String toString() {
return "name-" + name + " weight-" + weight;
}
@Override
public int compareTo(Cat o) {
//改這里
if (this.weight > o.weight) {
return 1;
} else if (this.weight < o.weight) {
return -1;
} else {
return 0;
}
}
}
結(jié)果:
但是還不夠完善啊延欠,雖然我不用動(dòng) DataSort類了陌兑,但我還是要?jiǎng)?Cat 類啊,有無方法由捎,DataSort 類和 Cat 類都不用動(dòng)呢兔综?
場(chǎng)景4.現(xiàn)在我修改對(duì)貓的其他屬性排序,對(duì)我們封裝好的東西不用動(dòng)(不用動(dòng) Cat,不用動(dòng) DataSort)软驰,只需要修改我們的 main 就可以涧窒。
- 程序設(shè)計(jì)4。給貓?zhí)砑右粋€(gè) --- 比較器锭亏。
/**
* Created by liangjunjie on 16/6/16.
* 比較器
*/
public interface Comparator<T> {
int compare(T o1, T o2);
}
/**
* Created by liangjunjie on 16/6/16.
* 貓的體重比較器
*/
public class CatWeightComparator implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
if(o1.weight > o2.weight) {
return 1;
} else if(o1.weight < o2.weight) {
return -1;
} else {
return 0;
}
}
}
/**
* Created by liangjunjie on 16/6/16.
*/
public class Cat implements Comparable<Cat>{
public String name;
public int weight;
public Cat(String name, int weight, Comparator comparator) {
this.name = name;
this.weight = weight;
this.comparator = comparator;
}
public Cat(String name, int weight) {
this.name = name;
this.weight = weight;
}
@Override
public String toString() {
return "name-" + name + " weight-" + weight;
}
@Override
public int compareTo(Cat o) {
//修改這里纠吴,根據(jù)傳入來的策略來比較
return comparator.compare(this, o);
}
}
/**
* Created by liangjunjie on 16/6/16.
* 排序工具
*/
public class DataSorter {
public static void sort(Comparable[] a) {
for(int i=a.length; i>0; i--) {
for(int j=0; j<i-1; j++) {
Comparable o1 = a[j];
Comparable o2 = a[j+1];
if(o1.compareTo(o2) == 1) {
swap(a, j , j+1);
}
}
}
}
private static void swap(Comparable[] a, int x, int y) {
Comparable temp = a[x];
a[x] = a[y];
a[y] = temp;
}
}
/**
* Created by liangjunjie on 16/6/16.
*/
public class MainActivity extends Activity{
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv_content);
//修改這里
CatNameComparator nameComparator = new CatNameComparator();
//數(shù)組創(chuàng)建
Cat kitty = new Cat("kitty", 3, nameComparator);//kitty,3kg慧瘤,1year
Cat tony = new Cat("tony", 5, nameComparator);//tony戴已, 5kg, 2year
Cat himit = new Cat("himit2", 6, nameComparator);//himt, 6kg 3year
Cat a[] = {kitty, tony, himit};
//數(shù)組排序
DataSorter.sort(a);
//數(shù)組輸出到界面
tv.setText(toStringArray(a));
}
/**
* 把數(shù)組轉(zhuǎn)成一段字符串輸出到界面
* @param a
* @return 一段排好序的字符串
*/
public String toStringArray(Cat[] a) {
String str = "";
for(int i=0; i<a.length; i++) {
str += a[i].toString() + "\n";
}
return str;
}
}
這樣子锅减,默認(rèn)就是按照了 weight 進(jìn)行排序了
結(jié)果:
貌似上面的真的還有一個(gè)地方不靠譜糖儡,每次 newcat 的時(shí)候也傳入一個(gè)比較器,所以想了一下怔匣,比較器應(yīng)該是在 DataSort 類的時(shí)候傳入去的握联,所以修改成這樣
- 程序設(shè)計(jì)4,Comparable 接口可以不用了
/**
* Created by liangjunjie on 16/6/16.
*/
public class MainActivity extends Activity{
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv_content);
CatNameComparator nameComparator = new CatNameComparator();
//數(shù)組創(chuàng)建
Cat kitty = new Cat("kitty", 3);//kitty每瞒,3kg金闽,1year
Cat tony = new Cat("tony", 5);//tony, 5kg独泞, 2year
Cat himit = new Cat("himit2", 6);//himt, 6kg 3year
Cat a[] = {kitty, tony, himit};
//數(shù)組排序
DataSorter.sort(a, nameComparator);
//數(shù)組輸出到界面
tv.setText(toStringArray(a));
}
/**
* 把數(shù)組轉(zhuǎn)成一段字符串輸出到界面
* @param a
* @return 一段排好序的字符串
*/
public String toStringArray(Cat[] a) {
String str = "";
for(int i=0; i<a.length; i++) {
str += a[i].toString() + "\n";
}
return str;
}
}
/**
* Created by liangjunjie on 16/6/16.
* 比較器
*/
public interface Comparator<T> {
int compare(T o1, T o2);
}
public class Cat{
public String name;
public int weight;
public Cat(String name, int weight) {
this.name = name;
this.weight = weight;
}
@Override
public String toString() {
return "name-" + name + " weight-" + weight;
}
}
/**
* Created by liangjunjie on 16/6/16.
*/
public class CatNameComparator implements Comparator<Cat> {
@Override
public int compare(Cat o1, Cat o2) {
if(o1.name.length() > o2.name.length()) {
return 1;
} else if(o1.name.length() < o2.name.length()) {
return -1;
} else {
return 0;
}
}
}
/**
* Created by liangjunjie on 16/6/16.
* 排序工具呐矾, 修改了這個(gè)關(guān)鍵類
*/
public class DataSorter {
public static <T extends Comparable<? super T>> void sort(T[] a, Comparator<T> comparator) {
for(int i=a.length; i>0; i--) {
for(int j=0; j<i-1; j++) {
T o1 = a[j];
T o2 = a[j+1];
if(comparator.compare(o1, o2) >= 1) {
swap(a, j , j+1);
}
}
}
}
private static <T extends Comparable<? super T>> void swap(T[] a, int x, int y) {
T temp = a[x];
a[x] = a[y];
a[y] = temp;
}
}
/**
* Created by liangjunjie on 16/6/16.
*/
public class MainActivity extends Activity{
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv_content);
//修改這里
CatNameComparator nameComparator = new CatNameComparator();
//數(shù)組創(chuàng)建
Cat kitty = new Cat("kitty", 3);//kitty,3kg懦砂,1year
Cat tony = new Cat("tony", 5);//tony蜒犯, 5kg, 2year
Cat himit = new Cat("himit2", 6);//himt, 6kg 3year
Cat a[] = {kitty, tony, himit};
//數(shù)組排序
DataSorter.sort(a, nameComparator);
//數(shù)組輸出到界面
tv.setText(toStringArray(a));
}
/**
* 把數(shù)組轉(zhuǎn)成一段字符串輸出到界面
* @param a
* @return 一段排好序的字符串
*/
public String toStringArray(Cat[] a) {
String str = "";
for(int i=0; i<a.length; i++) {
str += a[i].toString() + "\n";
}
return str;
}
}
結(jié)果: