写代码常用到的设计模式

一,装饰者模式

Paste_Image.png

总结:装饰者模式,就是对于父类A(Component),子类 B(ConcreteComponent)和C(Decorator)分别重新A中的方法,B中对方法进行实现,C及其子类可以调用B中实现的方法,也可以进行方法的拓展

二,代理模式

可以查看这篇文章,http://blog.csdn.net/luanlouis/article/details/24589193

https://www.zhihu.com/question/20794107
作者:雨夜偷牛的人
链接:https://www.zhihu.com/question/20794107/answer/23330381
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

最近正好在看,特来挖坟。
关于动态代理设计模式很可能题主就在不知不觉中使用了,例如Spring中的AOP,Struts2中的拦截器等。

先来看静态代理模式代码:

package test;

public interface Subject   
{   
  public void doSomething();   
}


package test;

public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  


package test;

public class SubjectProxy implements Subject
{
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     subimpl.doSomething();
  }
}


package test;

public class TestProxy 
{
   public static void main(String args[])
   {
       Subject sub = new SubjectProxy();
       sub.doSomething();
   }
}

刚开始我会觉得SubjectProxy定义出来纯属多余,直接实例化实现类完成操作不就结了吗?后来随着业务庞大,你就会知道,实现proxy类对真实类的封装对于粒度的控制有着重要的意义。但是静态代理这个模式本身有个大问题,如果类方法数量越来越多的时候,代理类的代码量是十分庞大的。所以引入动态代理来解决此类问题。

先看代码:

package test;

public interface Subject   
{   
  public void doSomething();   
}


package test;

public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
}  


package test;

import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  

public class ProxyHandler implements InvocationHandler
{
    private Object tar;

    //绑定委托对象,并返回代理类
    public Object bind(Object tar)
    {
        this.tar = tar;
        //绑定该类实现的所有接口,取得代理类 
        return Proxy.newProxyInstance(tar.getClass().getClassLoader(),
                                      tar.getClass().getInterfaces(),
                                      this);
    }    

    public Object invoke(Object proxy , Method method , Object[] args)throws Throwable
    {
        Object result = null;
        //这里就可以进行所谓的AOP编程了
        //在调用具体函数方法前,执行功能处理
        result = method.invoke(tar,args);
        //在调用具体函数方法后,执行功能处理
        return result;
    }
}


public class TestProxy
{
    public static void main(String args[])
    {
           ProxyHandler proxy = new ProxyHandler();
           //绑定该类实现的所有接口
           Subject sub = (Subject) proxy.bind(new RealSubject());
           sub.doSomething();
    }
}

看完代码,现在我来回答,动态代理的作用是什么:

  1. Proxy类的代码量被固定下来,不会因为业务的逐渐庞大而庞大;
  2. 可以实现AOP编程,实际上静态代理也可以实现,总的来说,AOP可以算作是代理模式的一个典型应用;
  3. 解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变。

三,工厂模式

http://blog.csdn.net/jason0539/article/details/23020989
工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式
简单工厂就是利用factory类创建对象,
抽象工厂是用多个factory创建对象,

四,原型模式

http://blog.csdn.net/sbsujjbcy/article/details/49302717

五,模板方法模式

在Android源码中,View中的Draw()方法就是一个“模板方法”。它定义了一系列“Draw”过程,主要包括这几个步骤(截取自源代码):

    /*
     * Draw traversal performs several drawing steps which must be executed
     * in the appropriate order:
     *
     *      1. Draw the background
     *      2. If necessary, save the canvas' layers to prepare for fading
     *      3. Draw view's content
     *      4. Draw children
     *      5. If necessary, draw the fading edges and restore layers
     *      6. Draw decorations (scrollbars for instance)
     */

在view类的draw()函数中调用了onDraw和dispatchDraw函数,当继承View子类中,如果要重写或者扩展这个方法时,整个方法流程和基本内容不能够修改,子类只能通过扩展onDraw(Canvas canvas)和dispatchDraw(Canvas canvas)两个函数,使子类自己的View显示效果和别的具体子类的不同。现在来看看继承自View类的具体子类如何扩展Draw()模板方法显示自己的与众不同:


Paste_Image.png

TextView类中重写了OnDraw函数,SurfaceView重写了dispatchDraw()函数,ViewGroup类重写了dispatchDraw()函数。
根据模版方法中的方法,可以分为两大类:模版方法(Template Method)和基本方法(Primitive Method)。其中我们这里的例子Draw()函数就是一个“模板方法”。
而基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method):
抽象方法:一个抽象方法由抽象类声明,由具体子类实现。
具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。
钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。我们这里的onDraw()函数就是一个钩子方法。

六,外观模式

就是多了层封装,SDK常用到

七,build模式

建造(Builder)模式是一种对象构建的设计模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
在没有运用构造模式之前,我们可能会使用构造方法还设置初始化对象时候的参数,但是有了build模式,就可以通过build来进行选择性的传参并实例化对象。例如,Android常用的第三方请求网络库okhttp,

OkHttpClient client = new OkHttpClient.Builder()
 .connectTimeout(15, TimeUnit.SECONDS)
 .readTimeout(15, TimeUnit.SECONDS)
 .build();

OkHttpClient类中该方法如下,

public Builder() {
 dispatcher = new Dispatcher();
 protocols = DEFAULT_PROTOCOLS;
 connectionSpecs = DEFAULT_CONNECTION_SPECS;
 proxySelector = ProxySelector.getDefault();
 cookieJar = CookieJar.NO_COOKIES;
 socketFactory = SocketFactory.getDefault();
 hostnameVerifier = OkHostnameVerifier.INSTANCE;
 certificatePinner = CertificatePinner.DEFAULT;
 proxyAuthenticator = Authenticator.NONE;
 authenticator = Authenticator.NONE;
 connectionPool = new ConnectionPool();
 dns = Dns.SYSTEM;
 followSslRedirects = true;
 followRedirects = true;
 retryOnConnectionFailure = true;
 connectTimeout = 10_000;
 readTimeout = 10_000;
 writeTimeout = 10_000;
}

八 ,观察者模式

观察者模式的底层其实是回调,Java中一般可以继承Observable 和Observer来实现被观察者和观察者,在安卓中,更是运用大量的观察者模式,例如,BaseAdapter关联了一个DataSetObservable对象,并实现registerDataSetObserver和unregisterDataSetObserver两个方法实现注册和撤销Observer,方法notifyDataSetChanged间接调用Observer的实现者的onChange()方法,以达到通知数据改变的作用。使用ListView和BaseAdapter组合时,当BaseAdapter的item改变时,我们经常会调用notifyDataSetChanged(),通知Listview刷新。

public abstract class DataSetObserver {
 /**
 * This method is called when the entire data set has changed,
 * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
 */
 public void onChanged() {
 // Do nothing
 }

 /**
 * This method is called when the entire data becomes invalid,
 * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
 * {@link Cursor}.
 */
 public void onInvalidated() {
 // Do nothing
 }
}
public abstract class Observable<T> {
 /**
 * The list of observers. An observer can be in the list at most
 * once and will never be null.
 */
 protected final ArrayList<T> mObservers = new ArrayList<T>();

 /**
 * Adds an observer to the list. The observer cannot be null and it must not already
 * be registered.
 * @param observer the observer to register
 * @throws IllegalArgumentException the observer is null
 * @throws IllegalStateException the observer is already registered
 */
 public void registerObserver(T observer) {
 if (observer == null) {
 throw new IllegalArgumentException("The observer is null.");
 }
 synchronized(mObservers) {
 if (mObservers.contains(observer)) {
 throw new IllegalStateException("Observer " + observer + " is already registered.");
 }
 mObservers.add(observer);
 }
 }

 /**
 * Removes a previously registered observer. The observer must not be null and it
 * must already have been registered.
 * @param observer the observer to unregister
 * @throws IllegalArgumentException the observer is null
 * @throws IllegalStateException the observer is not yet registered
 */
 public void unregisterObserver(T observer) {
 if (observer == null) {
 throw new IllegalArgumentException("The observer is null.");
 }
 synchronized(mObservers) {
 int index = mObservers.indexOf(observer);
 if (index == -1) {
 throw new IllegalStateException("Observer " + observer + " was not registered.");
 }
 mObservers.remove(index);
 }
 }

 /**
 * Remove all registered observers.
 */
 public void unregisterAll() {
 synchronized(mObservers) {
 mObservers.clear();
 }
 }
}

可以看出,观察者并不一定要继承JDK中的Observable 和Observer。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容