一、 模板方法模式
定义算法骨架,允许子类为一个或多个步骤提供实现
适用:
- 一次性实现一个算法的不变部分,将可变行为留给子类
- 各个子类中公共的行为被提取出来集中到公共父类中,避免代码重复
优点:
- 提高复用性
- 提高扩展性
- 符合开闭原则
缺点:
- 类数目增加
- 增加系统实现的复杂度
- 父类添加新抽象方法,子类也要实现
public abstract class ACourse {
protected final void makeCourse() {
this.makePPT();
this.makeVideo();
if (needWriteArticle()) {
this.writeArticle();
}
this.packageCourse();
}
final void makePPT() {
System.out.println("制作PPT");
}
final void makeVideo() {
System.out.println("制作视频");
}
final void writeArticle() {
System.out.println("编写手记");
}
// 钩子方法
protected boolean needWriteArticle() {
return false;
}
abstract void packageCourse();
}
public class FECourse extends ACourse {
private boolean needWriteArticleFlag = false;
@Override
void packageCourse() {
System.out.println("提供课程的前端代码");
System.out.println("提供课程的图片等多媒体素材");
}
public FECourse(boolean needWriteArticleFlag) {
this.needWriteArticleFlag = needWriteArticleFlag;
}
@Override
protected boolean needWriteArticle() {
return this.needWriteArticleFlag;
}
}
二、 迭代器模式
提供一种方法,顺序访问一个集合对象中的各个元素,而不暴露对象的内部表示
适用:
- 访问集合对象内容
- 为遍历不同的集合结构提供统一接口
优点:
- 分离了集合对象的遍历行为
缺点:
- 类的个数成对增加
// 集合类
public interface CourseAggregate {
void addCourse(Course course);
void removeCourse(Course course);
CourseIterator getCourseIterator();
}
public class CourseAggregateImpl implements CourseAggregate {
private List courseList;
public CourseAggregateImpl() {
this.courseList = new ArrayList();
}
// remove add
@Override
public CourseIterator getCourseIterator() {
return new CourseIteratorImpl(courseList);
}
}
// 迭代器
public interface CourseIterator {
Course nextCourse();
boolean isLastCourse();
}
public class CourseIteratorImpl implements CourseIterator {
private List courseList;
private int position;
private Course course;
public CourseIteratorImpl(List courseList) {
this.courseList = courseList;
}
@Override
public Course nextCourse() {
System.out.println("返回课程,位置是: " + position);
course = (Course) courseList.get(position);
position++;
return course;
}
@Override
public boolean isLastCourse() {
if (position < courseList.size()) {
return false;
}
return true;
}
}
三、 策略模式
定义算法家族,分别封装,可以互相替换,算法的变化不影响用户
适用:
- 有很多类,区别仅在于行为不同
- 系统需要动态在几种算法中选择一种
优点:
- 符合开闭原则
- 避免使用多重条件转移
- 提高算法的保密性和安全性
缺点:
- 客户端需要知道所有策略类,并自行选择
- 产生很多策略类
public class PromotionActivity {
private PromotionStrategy promotionStrategy;
public PromotionActivity(PromotionStrategy promotionStrategy) {
this.promotionStrategy = promotionStrategy;
}
public void executePromotionStrategy() {
promotionStrategy.doPromotion();
}
}
// 策略
public interface PromotionStrategy {
void doPromotion();
}
public class ManJianPromotionStrategy implements PromotionStrategy{
@Override
public void doPromotion() {
System.out.println("满减促销,满200-20元");
}
}
public class FanXianPromotionStrategy implements PromotionStrategy{
@Override
public void doPromotion() {
System.out.println("返现促销,返回的金额存放到账户余额中");
}
}
四、 解释器模式
给定一个语言,定义文法的一种表示,并定义一个解释器,解释该语言
适用:
- 某个特定类型问题发生频率足够高
优点:
- 语法由很多类表示,易于扩展
缺点:
- 语法规则数目太多时,增加复杂度
五、 观察者模式
定义对象间一对多的依赖,多个观察者同时监听某一个主题对象,当主题变化时,所有观察者收到通知
适用:
- 关联行为场景,建立触发机制
优点:
- 观察者和被观察者之间建立抽象耦合
- 广播通信
缺点:
- 观察者间有过多的细节依赖,提高时间消耗及程序复杂度
- 避免循环调用
// 主题
public class Subject {
// 观察者数组
private Vector<Observer> oVector = new Vector<>();
public void addObserver(Observer observer) {
this.oVector.add(observer);
}
public void deleteObserver(Observer observer) {
this.oVector.remove(observer);
}
public void notifyObserver() {
for (Observer observer : this.oVector) {
observer.update();
}
}
}
public class ConcreteSubject extends Subject {
// 具体业务
public void doSomething() {
// ...
super.notifyObserver();
}
}
// 观察者
public interface Observer {
public void update();
}
public class ConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("收到消息,进行处理");
}
}
六、 备忘录模式
保存对象状态,以便在适当时候恢复
适用:
- 保存及恢复数据
- 想要恢复到之前状态
优点:
- 提供可恢复机制
- 存档信息封装
缺点:
- 资源占用
// 可以创建备忘录和恢复的普通对象
public class Originator {
private String state;
public Memento createMemento() {
return new Memento(state);
}
public void restore(Memento memento) {
this.state = memento.getState();
}
}
// 备忘录
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
// 备忘录管理者
public class Caretaker {
private Memento memento;
public Memento restoreMemento() {
return memento;
}
public void storeMemengto(Memento memento) {
this.memento = memento;
}
}
七、 命令模式
将请求封装成对象,以便使用不同的请求
解决应用程序中对象的职责及通信方式
适用:
- 请求调用者和请求接受者解耦
- 需要抽象出等待执行的行为
优点:
- 降低耦合
- 容易扩展新命令或一组命令
缺点:
- 增加类的数量,提高系统实现复杂度
// 命令
interface Command {
void execute();
}
class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
class LightOffCommand implements Command {
Light light;
public LightOffCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.off();
}
}
// 命令接受者
class Light {
public void on() {
System.out.println("打开电灯。。。");
}
public void off() {
System.out.println("关闭电灯。。。");
}
}
八、 中介者模式
定义一个对象,封装一组对象如何交互
适用:
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱
- 交互的公共行为,如果需要改变行为,可以增加新的中介者类
优点:
- 将一对多转化成一对一
- 类之间解耦
缺点:
- 中介者过多,导致系统复杂
abstract class Colleague {
public abstract void onEvent(Mediator mediator);
}
class Alarm extends Colleague {
@Override
public void onEvent(Mediator mediator) {
mediator.doEvent("alarm");
}
public void doAlarm() {
System.out.println("doAlarm()");
}
}
// 中介者
abstract class Mediator {
public abstract void doEvent(String eventType);
}
class ConcreteMediator extends Mediator {
private Alarm alarm;
public ConcreteMediator(Alarm alarm) {
this.alarm = alarm;
}
@Override
public void doEvent(String eventType) {
switch (eventType) {
case "alarm":
break;
}
}
}
九、 责任链模式
为请求创建一个接受次请求对象的链
适用:
- 一个请求的处理需要多个对象中的一个或几个协作
优点:
- 请求的发送者和接收者解耦
- 责任链可以动态组合
缺点:
- 责任链太长影响性能
- 责任链可能过多
interface ILeave {
String getName();
int getNum();
String getContent();
}
abstract class Handler {
protected Handler successor;
public Handler(Handler successor) {
this.successor = successor;
}
abstract void handleLeave(ILeave leave);
}
class GroupLeader extends Handler {
public GroupLeader(Handler successor) {
super(successor);
}
@Override
public void handleLeave(ILeave leave) {
System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
System.out.println("小组长审批:同意。");
if (successor != null) {
successor.handleLeave(leave);
}
}
}
class Manager extends Handler {
public Manager(Handler successor) {
super(successor);
}
@Override
public void handleLeave(ILeave leave) {
System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
System.out.println("部门经理审批:同意。");
}
}
十、 访问者模式
封装作用于某数据结构中各元素的操作
可以在不改变各元素的类的前提下,定义作用于这些元素的操作
适用:
- 一个数据结构包含很多类型对象
- 数据结构于数据操作分离
优点:
- 增加新操作很容易
缺点:
- 增加新数据结构困难
- 具体元素变更比较麻烦
public interface ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}
public class Computer implements ComputerPart {
ComputerPart[] parts;
public Computer() {
parts = new ComputerPart[] { new Mouse(), new Keyboard() };
}
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
for (int i = 0; i < parts.length; i++) {
parts[i].accept(computerPartVisitor);
}
computerPartVisitor.visit(this);
}
}
public class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
public class Mouse implements ComputerPart {
// accept
}
public interface ComputerPartVisitor {
public void visit(Mouse mouse);
public void visit(Keyboard keyboard);
public void visit(Computer computer);
}
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
// ...
}
public class Test {
public static void main(String[] args) {
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
}
}
十一、 状态模式
允许一个对象在其内部状态改变时,改变它的行为
状态转换图
适用:
- 一个对象存在多个状态,且可相互转换
优点:
- 将不同状态隔离
- 把状态转换逻辑,分布到State子类中,减少相互间依赖
- 增加新状态简单
缺点:
- 状态多的业务场景导致类数目增加,系统变得复杂
interface State {
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
}
class HasQuarterState implements State {
private GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("You can't insert another quarter");
}
@Override
public void ejectQuarter() {
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
@Override
public void turnCrank() {
System.out.println("You turned...");
gumballMachine.setState(gumballMachine.getSoldState());
}
@Override
public void dispense() {
System.out.println("No gumball dispensed");
}
}
class NoQuarterState implements State {
// ...
}
class SoldOutState implements State {
// ...
}
class SoldState implements State {
// ...
}
class GumballMachine {
private State soldOutState;
private State noQuarterState;
private State hasQuarterState;
private State soldState;
private State state;
private int count = 0;
public GumballMachine(int numberGumballs) {
count = numberGumballs;
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
if (numberGumballs > 0) {
state = noQuarterState;
} else {
state = soldOutState;
}
}
public void insertQuarter() {
state.insertQuarter();
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void turnCrank() {
state.turnCrank();
state.dispense();
}
public void setState(State state) {
this.state = state;
}
public void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count -= 1;
}
}
// getter ...
}