如下內容是分析安卓源碼所得:java
1: 使用默認樣式建立View的方式, 源碼文件 Button.Java android
注:此文參考http://www.linzenews.com/ 中的內容所寫,如侵刪!算法
2: 須要聲明默認樣式的屬性, 源碼文件 attrs.xml 設計模式
3:建立默認樣式, 源碼文件 styles.xml 安全
4:在APP主題中,引用默認樣式 themes.xml (注意這步不能忘記) app
源碼分析結束.框架
如下是我我的的使用經驗:ide
1:主題中引用 radioButton樣式 源碼分析
2:聲明默認樣式屬性 學習
3:建立默認樣式
4:使用默認樣式建立View
這篇博客咱們來介紹一下策略模式(Strategy Pattern,或者叫 Policy Pattern),也是行爲型模式之一。一般在軟件開發中,咱們爲了一個功能可能會設計多種算法和策略,而後根據實際使用狀況動態選擇對應的算法和策略,好比排序算法中的快速排序,冒泡排序等等,根據時間和空間的綜合考慮進行運行時選擇。
針對這種狀況,一個常規的方法是將多種算法寫在一個類中,每個方法對應一個具體的排序算法,或者寫在一個方法中,經過 if…else 或者 switch…case 條件來選擇具體的排序算法。這兩種方法咱們都成爲硬編碼,雖然很簡單,可是隨着算法數量的增長,這個類就會變得愈來愈臃腫,維護的成本就會變高,修改一處容易致使其餘地方的錯誤,增長一種算法就須要修改封裝算法類的源代碼,即違背了開閉原則和單一職責原則。
若是將這些算法或者策略抽象出來,提供一個統一的接口,不一樣的算法或者策略有不一樣的實現類,這樣在程序客戶端就能夠經過注入不一樣的實現對象來實現算法或者策略的動態替換,這種模式的可擴展性、可維護性也就更高,這就是下面講到的策略模式。
java/android 設計模式學習筆記目錄
策略模式定義了一系列的算法,並將每個算法封裝起來,並且使他們能夠相互替換,讓算法獨立於使用它的客戶而獨立變化。
策略模式的使用場景:
咱們來看看策略模式的 uml 類圖:
策略模式有三個角色:
據此咱們能夠寫出策略模式的通用代碼:
Stragety.class
public interface Stragety {
void algorithm();
}
ConcreteStragetyA.class 和 ConcreteStragetyB.class
public class ConcreteStragetyA implements Stragety{
@Override
public void algorithm() {
System.out.print("ConcreteStragetyA\n");
}
}
public class ConcreteStragetyB implements Stragety{
@Override
public void algorithm() {
System.out.print("ConcreteStragetyB\n");
}
}
默認策略類ConcreteStragetyDefault.class
public class ConcreteStragetyDefault implements Stragety{
@Override
public void algorithm() {
System.out.print("null stragety");
}
}
Context.class 和測試代碼
public class Context {
private Stragety stragety;
public Context() {
stragety = new ConcreteStragetyDefault();
}
public void algorithm() {
stragety.algorithm();
}
public void setStragety(Stragety stragety) {
if (stragety == null) {
throw new IllegalArgumentException("argument must not be null!!!");
}
this.stragety = stragety;
}
public static void main(String args[]) {
Context context = new Context();
context.setStragety(new ConcreteStragetyA());
context.algorithm();
context.setStragety(new ConcreteStragetyB());
context.algorithm();
}
}
代碼很簡單,一目瞭然,沒有if-else,沒有 switch-case。核心就是創建抽象,將不一樣的策略構建成一個個具體的策略實現,經過不一樣的策略實現算法替換,在簡化邏輯、結構的同時,加強系統的可讀性、穩定性和可擴展性,這對於較爲複雜的業務邏輯顯得更爲直觀,擴展也更加方便。
其實在 Android 源碼中策略模式使用的次數也是不少,你們常見的動畫中就有使用到策略模式:
public abstract class Animation implements Cloneable {
/** * The interpolator used by the animation to smooth the movement. */
Interpolator mInterpolator;
....
/** * Sets the acceleration curve for this animation. Defaults to a linear * interpolation. * * @param i The interpolator which defines the acceleration curve * @attr ref android.R.styleable#Animation_interpolator */
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}
....
/** * Gets the transformation to apply at a specified point in time. Implementations of this * method should always replace the specified Transformation or document they are doing * otherwise. * * @param currentTime Where we are in the animation. This is wall clock time. * @param outTransformation A transformation object that is provided by the * caller and will be filled in by the animation. * @return True if the animation is still running */
public boolean getTransformation(long currentTime, Transformation outTransformation) {
......
final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
applyTransformation(interpolatedTime, outTransformation);
......
}
}
Animation 類就是很典型用到策略模式的類,它裏面會有一個 Interpolator 插值器對象,用來在執行動畫的時候達到所須要的速度變化效果,系統提供的插值器有 LinearInterpolator(線性插值器,動畫的執行速度相等),AccelerateDecelerateInterpolator (加速減速插值器,動畫的執行起始加速,結尾減速),DecelerateInterpolator(減速插值器,速度隨着動畫的執行變慢),以及回彈插值器等等,感興趣的上網查閱一下相關資料便可(我曾經在android下拉刷新框架用過插值器的相關類,是一個頗有用的類)。
這裏我就仍然以 wiki 上的代碼爲例,商場在不一樣時段會有打折促銷活動,顧客在不一樣的時段分別進行購買,最後得出一個價格:
BillingStragety.class
interface BillingStrategy {
public double getActPrice(double rawPrice);
}
NormalStrategy.class 和 HappyHourStragety.class
// Normal billing strategy (unchanged price)
class NormalStrategy implements BillingStrategy {
@Override
public double getActPrice(double rawPrice) {
return rawPrice;
}
}
// Strategy for Happy hour (50% discount)
class HappyHourStrategy implements BillingStrategy {
@Override
public double getActPrice(double rawPrice) {
return rawPrice * 0.5;
}
}
Customer.class
class Customer {
private List<Double> drinks;
private BillingStrategy strategy;
public Customer(BillingStrategy strategy) {
this.drinks = new ArrayList<Double>();
this.strategy = strategy;
}
public void add(double price, int quantity) {
drinks.add(strategy.getActPrice(price * quantity));
}
// Payment of bill
public void printBill() {
double sum = 0;
for (Double i : drinks) {
sum += i;
}
System.out.println("Total due: " + sum);
drinks.clear();
}
// Set Strategy
public void setStrategy(BillingStrategy strategy) {
this.strategy = strategy;
}
}
main
public class StrategyPatternWiki {
public static void main(String[] args) {
Customer firstCustomer = new Customer(new NormalStrategy());
// Normal billing
firstCustomer.add(1.0, 1);
// Start Happy Hour
firstCustomer.setStrategy(new HappyHourStrategy());
firstCustomer.add(1.0, 2);
// New Customer
Customer secondCustomer = new Customer(new HappyHourStrategy());
secondCustomer.add(0.8, 1);
// The Customer pays
firstCustomer.printBill();
// End Happy Hour
secondCustomer.setStrategy(new NormalStrategy());
secondCustomer.add(1.3, 2);
secondCustomer.add(2.5, 1);
secondCustomer.printBill();
}
}
不一樣時段買的東西,最後得出一個價錢,多種算法動態切換,用戶不用去關心具體的內部細節。
策略模式主要是用來分離算法,在相同的行爲抽象下有不一樣的具體實現策略。這個模式很好的演示了開閉原則:定義抽象,增長新的策略只須要增長新的類,而後在運行中動態更換便可,沒有影響到原來的邏輯,從而達到了很好的可擴展性。
優勢:
缺點也很明顯,這固然也是不少設計模式的通病:類的增多,隨着策略的增長,子類也會變得繁多。