典型的三种组件协作模式
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()在此例中属于比较稳定的模块,属于整个算法的骨架已经在父类中实现。属于父类调用子类方法(晚绑定)。
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(); //调用上下文对象的方法来完成对具体策略实现的回调
}
}
策略接口角色IStrategy:用来约束一系列具体的策略算法,策略上下文角色ConcreteStrategy使用此策略接口来调用具体的策略所实现的算法。
具体策略实现角色ConcreteStrategy:具体的策略实现,即具体的算法实现。
策略上下文角色StrategyContext:策略上下文,负责和具体的策略实现交互,通常策略上下文对象会持有一个真正的策略实现对象,策略上下文还可以让具体的策略实现从其中获取相关数据,回调策略上下文对象的方法。
- 策略模式就是把各个平等的具体实现进行抽象、封装成为独立的算法类,然后通过上下文和具体的算法类来进行交互。
- 各个策略算法都是平等的,地位是一样的,正是由于各个算法的平等性,所以它们才是可以相互替换的。
- 虽然我们可以动态的切换各个策略,但是同一时刻只能使用一个策略。
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 准备就绪
其实就是发布订阅模式,发布者发布信息,订阅者获取信息;
订阅了就能收到信息,没订阅就收不到信息。
参考文档:李建中-(23种设计模式)
本文为原创文章,转在请注明出处!!!!