行为型设计模式总结

  • 观察者模式

Observer模式作用是当一个对象发生变化时,能够自动通知它的观察者刷新状态。Observer模式提供给关联对象一种同步通信的手段,使某个对象与其它依赖它的对象保持状态同步。

模式结构图:
模式的角色和职责

Subject(被观察者):被观察的对象。当被观察的状态发生变化时,需要通知队列中所有观察者对象。subject需要维持一个观察者对象的队列列表。
ConcreteSubject:被观察者的具体实现。
Observer(观察者):接口或抽象类。当subject的状态发生变化时,Observer对象将通过一个Callback函数得到通知。
ConcreteObserver:观察者的具体实现。

示例:

作者发布一篇简书文章,让所有订阅者都收到该文章。

文章Article类:

class Article {

    private String title;
    private String content;
    private String author;

    public String getTitle() {
        return title == null ? "" : title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content == null ? "" : content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getAuthor() {
        return author == null ? "" : author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

具体的被观察者ArticelOperation类:

/**
 * 被观察者需要继承Observable接口
 */
class ArticelOperation extends Observable {

    /**
     * 发布一篇文章
     */
    public void publish(String title, String content, String author) {
        Article article = new Article();
        article.setTitle(title);
        article.setContent(content);
        article.setAuthor(author);
        this.setChanged();  //通知状态改变

        this.notifyObservers(article); //通知所有观察者对象状态改变了
    }
}

两个观察者类Observer和Observer2:

class Observer implements java.util.Observer {

    @Override
    public void update(Observable o, Object arg) {
        Article article = (Article) arg;

        System.out.println(getClass().getSimpleName() + "  " + article.getTitle());
        System.out.println(getClass().getSimpleName() + "  " + article.getContent());
        System.out.println(getClass().getSimpleName() + "  " + article.getAuthor());

    }
}

class Observer2 implements java.util.Observer {

    @Override
    public void update(Observable o, Object arg) {
        Article article = (Article) arg;

        System.out.println(getClass().getSimpleName() + "  " + article.getTitle());
        System.out.println(getClass().getSimpleName() + "  " + article.getContent());
        System.out.println(getClass().getSimpleName() + "  " + article.getAuthor());

    }
}

执行测试:

    public static void main(String[] args) {

        //创建一个观察者文章作者
        ArticelOperation article = new ArticelOperation();
        //添加各个观察者进行监听
        article.addObserver(new Observer());
        article.addObserver(new Observer2());

        //作者发布文章
        //article调用publish会调用自身notifyObservers,通知各个observer对象调用自己的update方法,收到该事件的回调。
        article.publish("Android进阶解密", "解读Android源码", "刘皇叔");
    }

执行结果,两个观察者都收到了作者的发布内容。


  • 模板方法模式

定义一个操作的算法的骨架,而将一些算法操作步骤延迟到子类中。模板方法使得子类可以不改变算法的结构可重定义的某些特定步骤。

Template Method模式一般应用在具有以下条件的应用中:
1.具有统一的操作步骤或操作过程。
2.具有不同的操作细节。
3.存在多个具有同样操作步骤的应用场景,但某些具体的操作细节却各不相同。

模式结构图:
示例:

定义做饭的抽象,将具体做的细节延迟到子类去实现,并定义make方法,将操作步骤统一起来,方便按自己的顺序一次性调用。

public abstract class MakeFood {

    //准备食材
    abstract void prepare();

    //进行做饭
    abstract void doing();

    //装盘
    abstract void carryOut();

    //再将操作步骤统一起来
    public void make() {
        prepare();
        doing();
        carryOut();
    }
}

实现MakeFood接口,做两个菜,将具体做法自己实现。

/**
 * 做一个西红柿鸡蛋
 */
class MakeTomatoEgg extends MakeFood {

    @Override
    void prepare() {
        System.out.println("准备西红柿鸡蛋");
    }

    @Override
    void doing() {
        System.out.println("抄西红柿鸡蛋");
    }

    @Override
    void carryOut() {
        System.out.println("装盘");
    }
}

/**
 * 炒肉
 */
class MakeMeet extends MakeFood {

    @Override
    void prepare() {
        System.out.println("准备肉");
    }

    @Override
    void doing() {
        System.out.println("炒肉");
    }

    @Override
    void carryOut() {
        System.out.println("装盘");
    }
}

测试执行:

    public static void main(String[] args) {
        MakeFood makeFood = new MakeTomatoEgg();
//        MakeFood makeFood = new MakeMeet();
        makeFood.make();
    }

结果:


模板方法模式优缺点:

优点:封装不变部分,扩展可变部分;提取公共代码,便于维护;行为由父类控制,具体由子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,是的系统更加庞大。

  • 策略模式

策略模式指的是对象具备某个行为,但是在不同的场景中,该行为有不同的实现算法。

模式结构:

模式的角色和职责:
Strategy:策略(算法)抽象
ConcreteStrategy:各种策略(算法)的具体实现。
Context:策略的外部封装类,或者说策略的容器类。根据不同策略执行不同的行为。

示例:

加密模式有MD5加密和Des加密,使用不同策略就分别使用各自的加密方式。

策略接口

interface Strategy {

    public void encrypt();
}

Md5Strategy加密策略:

class Md5Strategy implements Strategy {

    @Override
    public void encrypt() {
        System.out.println("MD5加密");
    }
}

DesStrategy加密策略:

class DesStrategy implements Strategy {

    @Override
    public void encrypt() {
        System.out.println("DES加密");
    }
}

策略的容器类Context:

class Context {

    public Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void encrypt() {
        strategy.encrypt();
    }
}

执行测试:

    public static void main(String[] args) {

        Context context = new Context(new Md5Strategy());
//        Context context = new Context(new DesStrategy());
        context.encrypt();
    }

根据采用的不同Strategy实例,使用对应的算法策略。

策略模式优缺点:

优点:策略模式提供了管理相关的算法族的办法。
缺点:客户端必须知道所有的策略,并自行决定使用哪一个策略类。

  • 责任链模式

责任链(Chain of Responsibility)模式的定义:为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

优点:解耦,简化操作。
缺点:性能会有一点影响,调试不太方便。

示例:

仿照okhttp库做各种拦截器:

责任链接口

interface Interceptor {
    String chain(String data);
}

创建缓存拦截器:

class CacheInterceptor implements Interceptor {

    @Override
    public String chain(String data) {
        return data = data + "缓存拦截器处理 ->";
    }
}

创建请求拦截器:

class CallServerInterceptor implements Interceptor {

    @Override
    public String chain(String data) {
        return data = data + "请求拦截器处理 ->";
    }
}

把责任链集合起来,遍历调用各个责任链的处理方法,并将结果传递给下一个责任链:

class RealInterceptor {
    List<Interceptor> list = new ArrayList<>();

    public RealInterceptor() {
        list.add(new CacheInterceptor());
        list.add(new CallServerInterceptor());
    }

    public String request(String data) {
        for (Interceptor interceptor: list) {
            data = interceptor.chain(data);
        }
        return data;
    }
}

执行并打印结果:

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

推荐阅读更多精彩内容