两篇android设计模式.docx
- 文档编号:23395670
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:18
- 大小:113.45KB
两篇android设计模式.docx
《两篇android设计模式.docx》由会员分享,可在线阅读,更多相关《两篇android设计模式.docx(18页珍藏版)》请在冰豆网上搜索。
两篇android设计模式
一.Observer樣式應用於Android框架設計
来自:
1.Framework的反向控制
反向控制(InversionofControl)是應用框架(ApplicationFramework,簡稱AF)魅力的泉源。
其常見的實現機制有 二:
1)繼承(Inheritance)
----這與TemplateMethod樣式密切相關。
2)委託(Delegation)
----這與Observer樣式密切相關。
Android是個完全的AF,處處可見到反向控制的機制。
當你熟悉上述的兩種實現機制後,就會將之對應到TemplateMethod和Observer樣式。
然後藉由樣式來更深刻體會這些機制的設計意涵。
如此,除了更能活用Android之外,也能逐漸提升你自己設計新AF的興趣、能力和信心。
2.複習:
使用繼承(即TemplateMethod樣式)
茲複習你已經熟悉的TemplateMethod樣式,如下述之範例:
//Student.java
publicclassStudent{
privateStringm_name;
privateintm_credit;
Student(Stringna,intcr){
m_name=na;
m_credit=cr;
}
publicvoidprint(){
System.out.println(m_name+","+String.valueOf(template_computeTuition()));
}
publicfloattemplate_computeTuition(){
if(m_credit>6)m_credit=6;
returnhook_getValue(m_credit)+5000;
}
protectedfloathook_getValue(intcredit){
return(credit-1)*500;
}
}
//Graduate_Student.java
publicclassGraduate_StudentextendsStudent{
Graduate_Student(Stringna,intcr){
super(na,cr);
}
protectedfloathook_getValue(intcredit){
returncredit*700;
}
}
//Undergraduate_Student.java
publicclassUndergraduate_StudentextendsStudent{
Undergraduate_Student(Stringna,intcr){
super(na,cr);
}
}
//JMain.java
publicclassJMain{
publicstaticvoidmain(String[]args){
intcredit=5;
Graduate_Studentmike=newGraduate_Student("Mike",5);
mike.print();
Undergraduate_Studentlinda=newUndergraduate_Student("Linda",7);
linda.print();
}
}
這是以TemplateMethod樣式來實踐反向控制。
3.使用委託(即Observer樣式)
在TemplateMethod樣式裡,hookmethod的具體實現是撰寫在子類別裡。
使用委託時,則將hookmethod定義於獨立的類別裡,如下述的HookClass:
把hookmethod定義於另外的類別:
//HookClass.java
publicclassHookClass{
protectedfloatgetValue(intcredit){
return(credit-1)*500;
}
}
templatemethod委託HookClass類別之物件去處理客製化的部份:
//Student.java
publicclassStudent{
privateStringm_name;
privateintm_credit;
privateHookClasshookObject=null;
Student(Stringna,intcr){
m_name=na;
m_credit=cr;
}
publicvoidsetHook(HookClasshk){
hookObject=hk;
}
publicvoidprint(){
System.out.println(m_name+","+String.valueOf(template_computeTuition()));
}
publicfloattemplate_computeTuition(){
if(m_credit>6)m_credit=6;
returnhookObject.getValue(m_credit)+5000;
}
}
定義HookClass的子類別:
GraduateHook,並且讓Student的物件委託給GraduateHook子類別之物件:
//Graduate_Student.java
publicclassGraduate_StudentextendsStudent{
Graduate_Student(Stringna,intcr){
super(na,cr);
setHook(newGraduateHook());
}
privatestaticclassGraduateHookextendsHookClass{
@Override
protectedfloatgetValue(intcredit){
returncredit*700;
}
}
}
//JMain.java
publicclassJMain{
publicstaticvoidmain(String[]args){
intcredit=5;
Studentmike=newGraduate_Student("Mike",credit);
mike.print();
}
}
於是,Student類別的templatemethod呼叫了HookClass抽象類別的getValue()函數,進而反向呼叫到GraduateHook子類別的getValue()函數。
4.GoF的Observer樣式
在GoF的<
圖1Observer樣式[GoF]
這裡的Subject類別就對應到上述程式碼的Student類別。
ConcreteSubject就對應到Graduate_Student類別。
Observer類別對應到HookClass。
ConcreteObserver對應到GraduateHook類別。
5.Observer樣式又稱為Listener樣式
上述的範例可改寫為:
//IListener.java
publicinterfaceIListener{
floatgetValue(intcredit);
}
//Student.java
publicclassStudent{
privateStringm_name;
privateintm_credit;
privateIListenerplis=null;
Student(Stringna,intcr){
m_name=na;
m_credit=cr;
}
publicvoidsetListener(IListenerlis){
plis=lis;
}
publicvoidprint(){
System.out.println(m_name+","+String.valueOf(template_computeTuition()));
}
publicfloattemplate_computeTuition(){
if(m_credit>6)m_credit=6;
returnplis.getValue(m_credit)+5000;
}
}
//Graduate_Student.java
publicclassGraduate_StudentextendsStudent{
Graduate_Student(Stringna,intcr){
super(na,cr);
setListener(newGraduateListener());
}
privatestaticclassGraduateListenerimplementsIListener{
publicfloatgetValue(intcredit){
returncredit*700;
}
}
}
//JMain.java
publicclassJMain{
publicstaticvoidmain(String[]args){
intcredit=5;
Studentmike=newGraduate_Student("Mike",credit);
mike.print();
}
}
6.欣賞Android裡的Observer樣式(即Listener樣式)
欣賞Android程式範例
6.1畫面情境
撰寫程式
建立Android程式專案:
//ac01.java
packagecom.misoo.pkzz;
importandroid.app.Activity;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.Button;
publicclassac01extendsActivity{
@Override
publicvoidonCreate(Bundleicicle){
super.onCreate(icicle);
setContentView(R.layout.main);
Buttonbtn=(Button)findViewById(R.id.button);
Buttonbtn2=(Button)findViewById(R.id.button2);
btn.setBackgroundResource(R.drawable.gray);
btn.setOnClickListener(clickListener);
btn2.setBackgroundResource(R.drawable.byw);
btn2.setOnClickListener(clickListener_2);
}
OnClickListenerclickListener=newOnClickListener()
{
publicvoidonClick(Viewv){
Stringname=((Button)v).getText().toString();
setTitle(name+"buttonclicked");
}
};
OnClickListenerclickListener_2=newOnClickListener()
{
publicvoidonClick(Viewv)
{
finish();
}
};
}
圖2Android裡的Listener樣式
這裡的ac01就是ConcreteObserver;而onClick()就是hookmethod(或稱為primitivemethod)。
View就是Subject。
而Button則是ConcreteSubject。
二.新手攻略之设计模式
(一.)factory
Factory模式
Fctory模式主要分为SimpleFactory模式、FactoryMethod模式、AbstractFactory模式三种。
SimpleFactory模式
如上图所示的,Client代表了客户的角色,它只依赖于接口ProductInterface,而不关心特定的具体操作,如何产生ProductInterface的实例由SimpleFactory完成。
客户只要面对Factory,客户依赖于产品接口,产品的具体创建操作是可以与客户分离的。
FactoryMethod模式
FactoryMethod中的AbstractOperator中拥有一个抽象的factoryMethod()方法,它负责生成一个IProduct类型的对象,由于目前还不知道将如何实现这个类型,所以将其推迟至子类别中实现,在AbstractOperator中先实现IProduct操作,利用多态操作即可完成各种不同的IProduct类型的对象操作。
AbstractFactory模式
简单的说,在AbstractFactory模式中将具体的Product封装在具体Factory实现中,而客户仍只要面对Factory与Product的抽象介面,避免依赖于具体的Factory与Product,由于Factory封装了所必须的Product,所以要更换掉所有的元件,只要简单的抽换掉Factory就可以了,不用修改客户端的代码。
以上就是Factory模式的基本结构和用法,一般来说:
使用factory模式
1)可以完成一系列的初始化操作。
比方说有一个类A,最简单的当然是Aa=newA()了,但是可能想做一些初始化工作,那最简单的我们就会把这些操作写在A的构造函数里面,如:
Aa=newA(param)了,但如果有很多的初始化工作,那把所有的初始化放在构造函数里面,可能就不大合适了,在这种情形下可以使用工厂模式,协助完成一系列初始化。
2)封装对象的创建。
在一个大程序中可能一个接口有很多类的实现,那在不同的地方就会写很多的
Interfaceintr1=newImpl1();
Interfaceintr2=newImpl2();
….
根据这样程序的扩展性、可维护性都会变差。
比较好的做法是:
Interfaceintr1=XXXFactory.getImpl1();
Interfaceintr2=XXXFactory.getImpl2();
但是这样的话,每当多一个实现,Factory接口就要多一个方法,这样Factory接口就经常需要变动,要解决这个问题,也有不少方法。
采用AbstractFactory模式,AbstractFactory的子类通过多态来实现:
Interfaceintr1=Impl1Factory.getImpl1();
Interfaceintr2=Impl2Factory.getImpl2();
这样做可以使接口封闭,但是增加类这个做法也不是太好,所以不推荐。
采用Interfaceintr1=XXXFactory.getImpl(param1);
这样的形式,这个应该是比较推荐的。
此外还可以采用template模式的方法,以后可以继续介绍。
3)使产品类的创建能够动态改变。
在工厂的方法中,可以采用动态加载类的方式来加载产品类。
这样如果碰到需要改变产品类的实现时,只需要修改配置而不需要更改和重新编译任何现有代码,使系统的扩展性大大加强。
此外,需要注意的是,一般来说Factory类的实例都采用Singleton模式来实现。
因为创建一个Factory的实例系统开销比较大,而且Factory主要是用来创建其它Product类的,一般不可能有很多个,所以将Factory类用Singleton模式来实现可以节约系统成本,提高运行效率。
如果大家对于Factory模式的使用还有什么经验总结的话,欢迎大家积极回复。
(二.)builder与prototype
2009-01-05|15:
38分类:
未分类|作者:
Sean|257views
Builder模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们,用户不知道内部的具体构建细节。
在实际使用中,我们经常在下面的场景中见到Builder的身影:
我们经常会用到一个概念——”池”(Pool),当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池。
“池”实际是一段内存,当池中有一些复杂的资源的”断肢”(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些”断肢”,将提高内存使用效率,提高池的性能。
修改Builder模式中Director类使之能诊断”断肢”断在哪个部件上,再修复这个部件。
看到这里,我们不禁会联想到上节中的一个模式:
AbstractFactory。
猛地一看,Builder模式的构造与AbstractFactory模式的确十分相像。
但是两者在应用场景和应用方式上还是有不少区别的。
Builder的概念在于,由Director使用Builder提供的BuildXxx的接口一步一步的构建一个目标对象,当然,Builder只是个抽象基类,Director使用的其实是Builder的一个实例,但是它并不知道用的是哪个实例。
每个实例产生的Product不同,所以Director同样也不知道产生了什么产品。
而AbstractFactory的概念在于,把目标对象视为Product,负责构建对象的类视为Factory。
对于所有的Product要遵循AbstractProduct的接口,同样所有的Factory也要遵循AbstractFactory的接口。
这样的好处呢,就是对于客户Client看到的,不再是具体的工厂和产品,而是都使用抽象工厂和抽象产品的接口,这是接口固定且一致,便容易多了。
两者的主要区别有下:
Builder是在Director的引导下,一步一步的构建对象;而AbstractFactory则是一次性创建对象。
对于AbstractFactory,客户直接操作Factory和Product,所以两者都要抽象出接口;而Builder模式下,Director只操作Builder实例,不直接操作Product,所以Product是什么样,什么接口对于Director压根不关心,自然也就不必抽象出接口。
Prototype模式
Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:
通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。
Prototype模式的一大特点就是提供了一种快捷的创建对象的方式。
一般在程序中我们可以使用的对象创建方法有:
1.使用new关键字创建对象,这是最最普通的一种。
2.使用对象序列化(Serialize)创建对象
3.使用反射机制(Reflection)动态创建对象
4.使用clone(克隆)方式创建对象
这里的Prototype模式用的就是第4种方法,它通过复制一个已经存在的对象实例来创建新的对象实例,被复制的对象实例称为”原型”。
原型模式多应用在创建复杂的或者耗时的实例,因为在这种情况下通过复制一个已经存在的对象使得程序的运行效率更高;或者值相等而命名不一样的同类数据。
Prototype模式的重点在于clone(),它负责复制物件本身并传回,但这个clone()本身在实作上存在一些困难,尤其是当物件本身又继承另一个物件时,如何确保复制的物件完整无误,这是个比较困难的问题。
但是,因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单。
Java语言的构件模型直接支持原型模式。
所有的类都继承自java.lang.Object,而Object类提供一个clone()方法,可以将一个类复制一份;但是这个类必须实现一个标示接口Cloneable表明这个类支持复制。
如果一个对象没有实现这个接口而调用clone()方法,Java编译器会抛出CloneNotSupportedException异常。
从功能上讲,Prototype模式的主要特点包括客户端不知道具体产品类,而只知道抽象产品类,客户端不需要知道这么多的具体产品名称。
如果有新的产品类加入,客户端不需要进行改造就可直接使用。
这一点我们又不禁联想到之前提到的AbstractFactory模式。
的确AbstractFactory模式有许多与Prototype模式相同的效果,但是两者的使用范围却不相同。
假设一个系统的产品类是动态加载的,而且产品类具有一定的等级结构。
这个时候如果采取工厂模式的话,工厂类就不得不具有一个相应的等级结构;而产品类的等级结构一旦变化,工厂类的等级结构就不得不有一个相应的变化。
这对于产品结构可能会有经常性变化的系统来说,采用工厂模式就有不方便之处。
在这种时候如果采取Prototype模式,给每一个产品类配备一个克隆方法(大多数的时候只需给产品类等级结构的根类配备一个克隆方法),便可以避免使用工厂模式所带来的具有固定等级结构的工厂类。
这样,一个使用了Prototype模式的系统与它的产品对象是怎么创建出来,以及这些产品对象之间的结构是怎样的,以及这个结构会不会发生变化是没有关系的。
Prototype模式又有其特有的优点:
第一、Prototype模式允许动态地增加或减少产品类。
由于创建产品类实例的方法是产品类内部具有的,因此增加新产品对整个结构没有影响。
第二、Prototype模式提供简化的创建结构。
工厂方法模式常常需要有一个与产品类等级结构相同的等级结构,而Prototype模式就不需要这样。
对于Java设计师来说,Prototype模式又有其特有的方便之处,因为Java语言天生就将Prototype模式设计到了语言模型里面。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- android 设计 模式