23种设计模式(一)-组件协作模式

典型的三种组件协作模式

Template Method:模板方法模式

在软件构建过程中,对于某项任务,常常有稳定的整体操作结构,但是各个子步骤却有很多改变的需求,或者由于固有的原因无法和任务整体结构同时实现。

定义一个算法的骨架,讲一些步骤(变化的)延迟到子类中,是的子类可以复用一个算法的结构(骨架)并重新定义(overwrite)某些特定的步骤

eg1:不使用Template Method
public class TemplateMethod {
    public boolean stap2() {
        return false;
    }

    public void stap4() {
    }

    public void run() {
        TemplateMethod templateMethod = new TemplateMethod();
        Lib lib = new Lib();
        try {
            lib.stap1();
            if (templateMethod.stap2()) {
                lib.stap3();
            } else {
                templateMethod.stap4();
            }
            lib.stap5();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class Lib {
    public void stap1() {
    }

    public boolean stap3() {
        return false;
    }

    public void stap5() {
    }
}

弊端:TemplateMethod 要实现 run()、 stap2() 、stap4()方法,然而run()在此例中属于比较稳定的模块,属于整个算法的骨架。属于子类调用父类方法(早绑定)

eg2:使用Template Method
public class TemplateMethod2 extends Lib2 {

    @Override
    public boolean stap2() {//变化点
        return false;
    }

    @Override
    public void stap5() {//变化点
    }

    public static void main(String[] args) {
        Lib2 templateMethod2 = new TemplateMethod2();
        templateMethod2.run();
    }
}

abstract class Lib2 {
    public void stap1() {
    }

    public abstract boolean stap2();// 声明为抽象方法

    public boolean stap3() {
        return false;
    }

    public void stap4() {
    }

    public abstract void stap5(); // 声明为抽象方法

    public void run() {  //稳定骨架(模板)
        try {
            stap1();
            if (stap2()) {
                stap3();
            } else {
                stap4();
            }
            stap5();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优点:TemplateMethod2 要实现 stap2() 、stap4()方法,然而run()在此例中属于比较稳定的模块,属于整个算法的骨架已经在父类中实现。属于父类调用子类方法(晚绑定)。

模板方法模式类图.png

Strategy:策略模式

在软件构建过程中,某些对象使用个算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使得对象变得异常复杂;而且有时候支持不是用的算法也是一个性能负担。

定义一系列算法,把它们一个个封装起来,并且使它们可以互相替换(变化)。该模式使得算法可以独立于使用它的客户程序(稳定)而变化(扩展、子类化).

//策略接口
public interface Strategy {
    //定义的抽象算法方法 来约束具体的算法实现方法
    public void algorithmMethod();
}

// 具体的策略实现1
class ConcreteStrategy1 implements Strategy {
    //具体的算法实现
    @Override
    public void algorithmMethod() {
        System.out.println("ConcreteStrategy1");
    }
}

// 具体的策略实现2
class ConcreteStrategy2 implements Strategy {
    //具体的算法实现
    @Override
    public void algorithmMethod() {
        System.out.println("ConcreteStrategy2");
    }
}

//策略上下文
class StrategyContext {
    private Strategy strategy;//持有一个策略实现的引用

    public StrategyContext(Strategy strategy) { //使用构造器注入具体的策略类
        this.strategy = strategy;
    }

    public void contextMethod() {
        strategy.algorithmMethod(); //调用策略实现的方法
    }
}

class Client {
    public static void main(String[] args) {
        Strategy concreteStrategy1 = new ConcreteStrategy1(); //创建具体测策略实现
        StrategyContext strategyContext = new StrategyContext(concreteStrategy1); //在创建策略上下文的同时,将具体的策略实现对象注入到策略上下文当中
        strategyContext.contextMethod(); //调用上下文对象的方法来完成对具体策略实现的回调
    }
}
策略模式(Strategy)类图.png
  1. 策略接口角色IStrategy:用来约束一系列具体的策略算法,策略上下文角色ConcreteStrategy使用此策略接口来调用具体的策略所实现的算法。

  2. 具体策略实现角色ConcreteStrategy:具体的策略实现,即具体的算法实现。

  3. 策略上下文角色StrategyContext:策略上下文,负责和具体的策略实现交互,通常策略上下文对象会持有一个真正的策略实现对象,策略上下文还可以让具体的策略实现从其中获取相关数据,回调策略上下文对象的方法。

  1. 策略模式就是把各个平等的具体实现进行抽象、封装成为独立的算法类,然后通过上下文和具体的算法类来进行交互。
  2. 各个策略算法都是平等的,地位是一样的,正是由于各个算法的平等性,所以它们才是可以相互替换的。
  3. 虽然我们可以动态的切换各个策略,但是同一时刻只能使用一个策略

Observer/Event:事件模式

定义对象间的一种一对多(变化)的依赖关系,以便当一个对象(Subject)的状态发生改变时候,所有依赖于它的对象都等到通知并自动更新

/**
 * @author lillcol
 * 2019/6/13-23:38
 */
//被观察者抽象类
public abstract class Subject {
    abstract void attack(Observer observer);//添加观察者

    abstract void dettack(Observer observer);//移除观察者

    abstract void notifyObserver();//通知观察者

    abstract void operation();//被观察者状态变化
}

//被观察者抽象类
abstract class AbstractSubject extends Subject {
    private List<Observer> observerList = new ArrayList<>(); //观察者对象集合

    @Override
    void attack(Observer observer) {//添加观察者
        observerList.add(observer);
    }

    @Override
    void dettack(Observer observer) {//移除观察者
        observerList.remove(observer);
    }

    @Override
    void notifyObserver() {
        for (Observer observer : observerList) {
            observer.update();
        }
    }
}

//被观察者实现类
class ConcreteSubject extends AbstractSubject {
    @Override
    void operation() {
        System.out.println("ConcreteSubject 要搞事情了");
        notifyObserver();   // 通知所有观察者
    }
}

//观察者抽象类
abstract class Observer {
    public String name;
    abstract void setName(String name);//设置名字

    abstract String getName();//获取名字

    abstract void update();//观察者更新方法
}

class ConcreteObserver1 extends Observer{

    @Override
    void setName(String name) {
        this.name=name;
    }

    @Override
    String getName() {
        return this.name;
    }

    @Override
    void update() {
        System.out.println("伞兵一号 ConcreteObserver1 准备就绪");
    }
}

class ConcreteObserver2 extends Observer{

    @Override
    void setName(String name) {
        this.name=name;
    }

    @Override
    String getName() {
        return this.name;
    }

    @Override
    void update() {
        System.out.println("伞兵二号 ConcreteObserver2 准备就绪");
    }
}
//测试案例:
class Test{
    public static void main(String[] args) {
        ConcreteSubject concreteSubject = new ConcreteSubject();
        ConcreteObserver1 concreteObserver1 = new ConcreteObserver1();
        ConcreteObserver2 concreteObserver2 = new ConcreteObserver2();
        concreteSubject.attack(concreteObserver1);
        concreteSubject.attack(concreteObserver2);
        concreteSubject.operation();
        System.out.println("------");
        concreteSubject.dettack(concreteObserver1);
        concreteSubject.operation();
    }
}
//输出:
ConcreteSubject 要搞事情了
伞兵一号 ConcreteObserver1 准备就绪
伞兵二号 ConcreteObserver2 准备就绪
------
ConcreteSubject 要搞事情了
伞兵二号 ConcreteObserver2 准备就绪
观察者模式-类图.png

其实就是发布订阅模式,发布者发布信息,订阅者获取信息;
订阅了就能收到信息,没订阅就收不到信息。

参考文档:李建中-(23种设计模式)
本文为原创文章,转在请注明出处!!!!

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

推荐阅读更多精彩内容