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种设计模式)
本文为原创文章,转在请注明出处!!!!

posted @ 2019-07-04 00:17  lillcol  阅读(744)  评论(0编辑  收藏  举报