设计模式是程序员进阶的必经之路,这也是我的必经之路,也许大家当初为了面试所需都强记过一些设计模式的名字,像单例模式,工厂模式,策略模式,观察者模式,代理模式,适配器模式,命令模式等等。我当初就是知其然不知其所以然,现在决定把设计模式都认真学习一遍,没有代码量是不可能成功的,所以在学习过程中,记录下所有代码。见证成长。
那么先从最简单的工厂模式开始,工厂模式,顾名思义就是生产实例的工厂。也就是在设计层中同一层有过多的相似功能的类,就可以使用工厂类来简化实例。
举个例子(安卓的代码),很简单的一个计算器程序,很多在校大学生或者玩过代码的初高中生都能编出来。
对于该需求,先将业务逻辑和界面逻辑分层。界面逻辑在该需求中并不复杂,所以没必要在细分。
业务逻辑可以继续细分,计算器的逻辑中将可变和不可变的部分进行分层,不可变的共有的放在父类,也就是两个进行计算的参数
图示:
public abstract class Operation {
private double numA;
private double numB;
public double getNumA() {
return numA;
}
public void setNumA(double numA) {
this.numA = numA;
}
public double getNumB() {
return numB;
}
public void setNumB(double numB) {
this.numB = numB;
}
public double getResultMoney(){
return 0;
}
}
然后就是对计算父类进行继承,这里分层最主要是考虑用户需求的改变,比如再添一个开方,根号的计算,分层有利于提高代码的可扩展性。
public class OperationAdd extends Operation {
@Override
public double getResultMoney() {
return getNumA()+getNumB();
}
}
计算逻辑分层好了之后,就可以在计算具体实现(加减乘除)这个层加一个工厂类,根据需求提供不同实例,用父类的引用来接受,这样可以进一步简化代码。
public class OperationFactory {
public static Operation createOperation(int flag,Context context){
Operation operation = null;
switch (flag){
case 0:
operation = new OperationAdd();
break;
case 1:
operation = new OperationSub();
break;
case 2:
operation = new OperationMul();
break;
case 3:
operation = new OperationDiv(context);
break;
}
return operation;
}
}
具体使用就在自定义的控件了。这里的operation使用多态,提高代码的可复用性。
case R.id.calwait:
numB = Double.parseDouble(textView.getText().toString());
stringBuilder.delete(0, stringBuilder.length());
Operation operation = OperationFactory.createOperation(flag,context);
operation.setNumA(numA);
operation.setNumB(numB);
double result = operation.getResultMoney();
textView.setText(String.valueOf(result));
break;
自定义的计算器控件
package com.abings.factorymodel.Calcumater;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.abings.factorymodel.Operation.Operation;
import com.abings.factorymodel.Operation.OperationFactory;
import com.abings.factorymodel.R;
/**
* Created by Shuwen on 2016/8/24.
*/
public class CalcumateView extends LinearLayout {
private TextView textView;
final StringBuilder stringBuilder = new StringBuilder();
private Context context;
private double numA;
private double numB;
private Button[]btns = new Button[18];
//尽可能的使代码简化
private int[]nums = new int[]{R.id.num0,R.id.num1,R.id.num2,R.id.num3,R.id.num4
,R.id.num5,R.id.num6,R.id.num7,R.id.num8,R.id.num9,R.id.caladd,R.id.calsub
,R.id.calmul,R.id.caldiv,R.id.calwait,R.id.clearall,R.id.delete,R.id.numdot};
private int flag = 0;
public CalcumateView(Context context) {
this(context,null);
}
public CalcumateView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CalcumateView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
LayoutInflater.from(context).inflate(R.layout.calculater, this);
initViews();
setEvents();
}
private void setEvents() {
//数字,加减乘除
for (int i = 0; i < nums.length; i++) {
setNumOnclick(btns[i]);
}
}
public void setNumOnclick(final Button button){
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.caladd:
numA = Double.parseDouble(textView.getText().toString());
stringBuilder.delete(0,stringBuilder.length());
flag = 0;
textView.setText(stringBuilder);
break;
case R.id.calsub:
numA = Double.parseDouble(textView.getText().toString());
stringBuilder.delete(0,stringBuilder.length());
flag = 1;
textView.setText(stringBuilder);
break;
case R.id.calmul:
numA = Double.parseDouble(textView.getText().toString());
stringBuilder.delete(0,stringBuilder.length());
flag = 2;
textView.setText(stringBuilder);
break;
case R.id.caldiv:
numA = Double.parseDouble(textView.getText().toString());
stringBuilder.delete(0,stringBuilder.length());
flag = 3;
textView.setText(stringBuilder);
break;
case R.id.calwait:
numB = Double.parseDouble(textView.getText().toString());
stringBuilder.delete(0, stringBuilder.length());
Operation operation = OperationFactory.createOperation(flag,context);
operation.setNumA(numA);
operation.setNumB(numB);
double result = operation.getResultMoney();
textView.setText(String.valueOf(result));
break;
case R.id.clearall:
stringBuilder.delete(0, stringBuilder.length());
textView.setText(stringBuilder);
break;
case R.id.delete:
int len = stringBuilder.length() - 1 > 0?stringBuilder.length() - 1:0;
stringBuilder.delete(len, stringBuilder.length());
textView.setText(stringBuilder);
break;
default:
stringBuilder.append(button.getText());
textView.setText(stringBuilder);
break;
}
}
});
}
private void initViews() {
for (int i = 0;i < nums.length;i++){
btns[i] = (Button) findViewById(nums[i]);
}
textView = (TextView) findViewById(R.id.text);
}
}
这篇博客最主要是介绍工厂模式,好了。工厂模式还是相当简单明了易上手。
最后附上项目git:(在新的网页打开)
https://github.com/SingleShu/FactoryModel