Java及Android常用设计模式

在你的程序中应用一些设计模式让你的代码组织更有条理。懂得设计模式让你更容易看懂一些优秀的源码。本文逐步摸索各种设计模式。

1、对象的适配器模式

2、工厂方法模式

下面URL作为工厂类,URLConnection作为抽象产品,具体产品为HttpURLConnectionImpl。

URL url = new URL("http://qinuli.com");
//HttpURLConnectionImpl
//抽象类,Factory Method Pattern
URLConnection urlConnection = url.openConnection();
Log.d(TAG, Thread.currentThread().getName()+"|"+urlConnection.getClass().getSimpleName());
BufferedReader bufferedReader = new BufferedReader(
	new InputStreamReader(urlConnection.getInputStream()));
Log.d(TAG, "before read");
String str;
while((str=bufferedReader.readLine())!=null){
	Log.i(TAG, str);
}

断网情况下,getInputStream()会报如下异常

3、观察者模式

观察者是一种很常见的设计模式,在Android中经常用到。比如SharedPreferences.registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener),

ContextWrapper.registerReceiver(BroadcastReceiver, IntentFilter)等。

MyApplication.java

public class MyApplication extends Application {
	private static MyApplication me;
	private DataCenter mDataCenter;
	public MyApplication(){
		super();
		me = this;
	}
	public static MyApplication getInstance(){
		return me;
	}
	@Override
	public void onCreate() {
		super.onCreate();
		mDataCenter = new DataCenter();
	}
	public DataCenter getDataCenter(){
		return mDataCenter;
	}
}
MainActivity.java
public class MainActivity extends Activity {
	private static final String TAG = MainActivity.class.getSimpleName();
	private ChildView mChildView;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		ViewGroup viewGroup = new FrameLayout(this);
		LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
		viewGroup.setLayoutParams(layoutParams);//ignored
		LayoutInflater.from(this).inflate(R.layout.activity_main, viewGroup);
		setContentView(viewGroup, layoutParams);
		
		mChildView = (ChildView) findViewById(R.id.view);
		MyApplication.getInstance().getDataCenter().addObserver(mChildView);
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		MyApplication.getInstance().getDataCenter().deleteObserver(mChildView);
	}
	public void onClick(View v){
		switch(v.getId()){
		case R.id.btn:
			EditText editText = (EditText) findViewById(R.id.edit);
			MyApplication.getInstance().getDataCenter().changeData(editText.getText().toString());
		}
	}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical">
    <EditText 
        android:id="@+id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>
    <Button 
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="ironman"/>
    <com.qinuli.commontemplate.ChildView
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</LinearLayout>
ParentView.java
public abstract class ParentView extends View {
	private static final String TAG = ParentView.class.getSimpleName();
	GestureDetector mGestureDetector;
	
	public ParentView(Context context){
		//单参供代码中实例化用
		//多参供xml文件用,2参调3参,3参调4参
		super(context);
	}
	public ParentView(Context context, AttributeSet attrs){
		super(context, attrs);
		init();
	}
	
	private void init(){
		mGestureDetector = new GestureDetector(getContext(), new MySimpleOnGestureListener());
	}
	
	/**
	 * 可共享外部类的属性方法
	 * 避免单继承的局限
	 */
	public class MySimpleOnGestureListener extends SimpleOnGestureListener{
		@Override
		public boolean onDown(MotionEvent e) {
			return true;
		}
		@Override
		public boolean onDoubleTap(MotionEvent e) {
			Log.i(TAG, "onDoubleTap");
			return true;
		}
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return mGestureDetector.onTouchEvent(event);
	}
	
	/**
	 * 静态方法依然可被继承、覆写
	 */
	public static void show(){
		Log.d(TAG, "show");
	}
}
ChildView.java
public class ChildView extends ParentView implements Observer{
	private static final String TAG = ChildView.class.getSimpleName();
	private Paint mPaint;
	private DisplayMetrics dm;
	
	public ChildView(Context context){
		super(context);
	}
	
	public ChildView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	private void init(){
		dm = getContext().getResources().getDisplayMetrics();
		mPaint = new Paint();mPaint.setTextSize(20f * dm.density);
		this.data = MyApplication.getInstance().getDataCenter().retrieveData();
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		Log.i(TAG, "onDraw");
		super.onDraw(canvas);
		for(int i=0;i<data.size();i++){
			canvas.drawText(data.get(i), 100f, 100f + i*40f, mPaint);
		}
	}
	public static void show(){
		Log.d(TAG, "show");
	}

	private List<String> data = new ArrayList<String>();
	@Override
	public void update(Observable observable, Object data) {
		this.data = MyApplication.getInstance().getDataCenter().retrieveData();
		invalidate();
	}
}
DataCenter.java
public class DataCenter extends Observable{
	private List<String> strs = new ArrayList<String>();
	public List<String> retrieveData(){
		return strs;
	}
	public void changeData(String data){
		this.strs.add(data);
		setChanged();
		notifyObservers(null);
	}
}
4、不变模式(Immutable Pattern)

不变模式即对象一旦创建其状态就不再变化,常见的有String(封装char[])、Integer(封装int)等

//不变子模式
//String封装一个char[]
String str = "welcome";
String str2 = new String(str);
String str3 = "welcome";
//相同对象
System.out.println("str==str3:"+(str==str3));
//不同对象但hashCode相同
System.out.println("str:"+str.hashCode()+";str2:"+str2.hashCode());
System.out.println(str.equals(str2)+"-"+(str==str2));

//final类,继承Number,将基本类型long封装为Object
//实例化时传入值,不再改变
Long l = new Long(5L);
Float f = new Float(5.0f);
//有些地方只能用Object,需要wrapper
Vector<Long> vector = new Vector<Long>();
vector.addElement(5L);

5、多例模式(Multiton Pattern)

多例模式特点为类不能从外部实例化,自行创建并向外部提供多个实例。多个实例使用私有静态聚集保存。

Locale locale = Locale.CHINA;//new Locale("zh", "CN");
//src目录下 bundle_zh_CN.properties
//使用了多例模式,支持多语言
ResourceBundle rb = ResourceBundle.getBundle("bundle", locale);
Log.d(TAG, rb.getString("name")+"-"+rb.getString("sex"));

//HashTable key/value必须string
Properties properties = new Properties();
properties.put("height", "175CM");
properties.put("weight", "70KG");
properties.setProperty("address", "BJ");//直接调用Hashtable.put
try {
	FileOutputStream fos = new FileOutputStream(Environment.getExternalStorageDirectory()+"/info.xml");
	FileInputStream fis = new FileInputStream(Environment.getExternalStorageDirectory()+"/info.xml");
	properties.storeToXML(fos, null, "UTF-8");
	properties.loadFromXML(fis);
	properties.getProperty("height");//Hashtable.get
	properties.list(System.out);
} catch (FileNotFoundException e) {
	e.printStackTrace();
} catch (IOException e) {
	e.printStackTrace();
}

bundle_zh_CN.properties

name=\u77f3\u946b
sex=male

6、listener模式

private static class DataDecodedListenerWrapper{
	boolean full;
	DataDecodedListener listener;
	public DataDecodedListenerWrapper(boolean full,
			DataDecodedListener listener) {
		this.full = full;
		this.listener = listener;
	}
	@Override
	public boolean equals(Object o) {
		DataDecodedListenerWrapper wrapper = (DataDecodedListenerWrapper) o;
		if(this.listener==wrapper.listener&&this.full==wrapper.full){
			return true;
		}
		return false;
	}
}

/**
 * <li>此处接口也用extends
 * <li>key用value的class保证某个类的对象仅存一个
 */
private Map<Class<? extends DataDecodedListener>, DataDecodedListener> mMap = new HashMap<Class<? extends DataDecodedListener>, BaseDecoder.DataDecodedListener>();
private List<DataDecodedListenerWrapper> mListeners2 = new ArrayList<DataDecodedListenerWrapper>();
private Map<DataDecodedListener, Boolean> mMap2 = new HashMap<DataDecodedListener, Boolean>();
public void registerListener2(DataDecodedListener listener, boolean full){
//		synchronized (mMap) {
//			if(!mMap.containsValue(listener)&&mMap.containsKey(listener.getClass())){
//				mMap.remove(listener.getClass());
//				mMap.put(listener.getClass(), listener);
//			}
//		}
	synchronized (mMap2) {
		if(!mMap2.containsKey(listener)){
			mMap2.put(listener, full);
		}
	}
}
public void unregisterListener2(DataDecodedListener listener){
//		synchronized (mMap) {
//			mMap.remove(listener.getClass());
//		}
	synchronized (mMap2) {
		mMap2.remove(listener);
	}
}
 
public void notifyAllDataDecodedListener(BaseDecoder decoder) {
//		synchronized (mMap) {
//			Set<Entry<Class<? extends DataDecodedListener>, DataDecodedListener>> set = mMap.entrySet();
//			Iterator<Entry<Class<? extends DataDecodedListener>, DataDecodedListener>> it = set.iterator();
//			while(it.hasNext()){
//				DataDecodedListener listener = it.next().getValue();
//				listener.onHealthDataDecoded(decoder);
//			}
//		}
//		synchronized (mListeners2) {
//			Iterator<DataDecodedListenerWrapper> it = mListeners2.iterator();
//			boolean full = BqfjApplication.isFullscreenMode();
//			while (it.hasNext()) {
//				DataDecodedListenerWrapper listenerWrapper = it.next();
//				if (listenerWrapper.full==full) {
//					listenerWrapper.listener.onHealthDataDecoded(decoder);
//				}
//			}
//		}
	synchronized (mMap2) {
		Set<Entry<DataDecodedListener, Boolean>> set = mMap2.entrySet();
		Iterator<Entry<DataDecodedListener, Boolean>> it = set.iterator();
		boolean full = BqfjApplication.isFullscreenMode();
		while(it.hasNext()){
			Entry<DataDecodedListener, Boolean> entry = it.next();
			DataDecodedListener listener = entry.getKey();
			if(entry.getValue()==full)
				listener.onHealthDataDecoded(decoder);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值