之前两篇文章中,创建型主要讲类的创建,结构型主要讲类的组合,行为型主要侧重类和类的交互。行为型占了设计模式中的一半,在源码中我们经常会看到这些设计模式。
行为型设计模式主要有以下几个
- 观察者模式
- 模板模式
- 策略模式
- 职责链模式
- 状态机模式
- 迭代器模式
- 访问者模式
- 命令模式
- 解释器模式
- 中介者模式
观察者模式
观察者模式主要用于对结果的通知处理,有点类似发布订阅,但是发布订阅可以多对多,观察者模式时一对多的形式。
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestObserver {
public static void main(String[] args) {
WeatherConsole weatherConsole = new WeatherConsole();
weatherConsole.registerNotifition(new TelNotifition());
weatherConsole.registerNotifition(new EmailNotifition());
weatherConsole.pubWeather("sun");
weatherConsole.pubWeather("rain");
weatherConsole.pubAsyncWeather("oh it's sun");
weatherConsole.pubAsyncWeather("oh it's rainy day");
}
}
interface Notifition {
void notifyMsg(String msg);
}
class EmailNotifition implements Notifition {
@Subscribe
public void notifyMsg(String msg) {
System.out.println("send Email" + msg);
}
}
class TelNotifition implements Notifition {
@Subscribe
public void notifyMsg(String msg) {
System.out.println("call telephone" + msg);
}
}
class WeatherConsole {
private EventBus eventBus = new EventBus();
private EventBus asyncEventBus = new AsyncEventBus(new ThreadPoolExecutor(5, 5, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()));
public void registerNotifition(Notifition notifition) {
eventBus.register(notifition);
asyncEventBus.register(notifition);
}
public void pubAsyncWeather(String weather) {
asyncEventBus.post(weather);
}
public void pubWeather(String weather) {
asyncEventBus.post(weather);
}
}
模板模式
模板模式主要用于当两个类继承同一个接口,但是其实类中部分方法时相同的时候,这个时候用模板模式,主要为了复用和扩展。
public class TestTemplate {
public static void main(String[] args) {
ClazzEntity clazzEntity = new ClazzEntity();
clazzEntity.setAuthor("germa");
clazzEntity.setClazzName("Clazz Event");
clazzEntity.setInfomation("clazz event is test class");
DescriptionClazzEvent descriptionClazzEvent = new DescriptionClazzEvent();
descriptionClazzEvent.setClazzEntity(clazzEntity);
System.out.println(descriptionClazzEvent.getBasicInfo());
System.out.println(descriptionClazzEvent.generateClazzId());
BizClazzEvent bizClazzEvent = new BizClazzEvent();
bizClazzEvent.setClazzEntity(clazzEntity);
System.out.println(bizClazzEvent.getBasicInfo());
System.out.println(bizClazzEvent.generateClazzId());
}
}
abstract class ClazzEvent {
protected ClazzEntity clazzEntity;
public void setClazzEntity(ClazzEntity clazzEntity) {
this.clazzEntity = clazzEntity;
}
public String getBasicInfo() {
return clazzEntity.getInfomation();
}
public abstract String generateClazzId();
}
class DescriptionClazzEvent extends ClazzEvent {
@Override
public String generateClazzId() {
return String.format("%s:%s:%s", clazzEntity.getInfomation(), clazzEntity.getAuthor(), clazzEntity.getClazzName());
}
}
class BizClazzEvent extends ClazzEvent {
@Override
public String getBasicInfo() {
return clazzEntity.getClazzName();
}
@Override
public String generateClazzId() {
return String.format("%s:%s", clazzEntity.getInfomation(), clazzEntity.getAuthor());
}
}
class ClazzEntity {
private String clazzName;
private String author;
private String infomation;
public String getClazzName() {
return clazzName;
}
public void setClazzName(String clazzName) {
this.clazzName = clazzName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getInfomation() {
return infomation;
}
public void setInfomation(String infomation) {
this.infomation = infomation;
}
}
策略模式
策略模式主要用于更具不同的类型,选择不同的对象,一般我们经常用if else if 这种去创建,这样子做的不足则是将策略的定义,创建和使用在一起呢。策略模式一般和工厂模式整合。
public class TestStrategy {
public static void main(String[] args) {
System.out.println(CarFactory.getCarByType(CarType.ELE_CAR).name());
System.out.println(CarFactory.getCarByType(CarType.MIX_CAR).name());
System.out.println(CarFactory.getCarByType(CarType.OIL_CAR).name());
}
}
interface Car {
String name();
}
class EleCar implements Car {
@Override
public String name() {
return "byd";
}
}
class OilCar implements Car {
@Override
public String name() {
return "bmw";
}
}
class MixCar implements Car {
@Override
public String name() {
return "wulin";
}
}
enum CarType {
ELE_CAR("ele car"),
OIL_CAR("oil car"),
MIX_CAR("mix car");
private String type;
private CarType(String type) {
this.type = type;
}
}
class CarFactory {
private static Map<CarType, Car> carMap = new HashMap<CarType, Car>();
static {
carMap.put(CarType.ELE_CAR,new EleCar());
carMap.put(CarType.OIL_CAR,new OilCar());
carMap.put(CarType.MIX_CAR,new MixCar());
}
public static Car getCarByType(CarType carType){
return carMap.get(carType);
}
}
职责链模式
职责链模式我们在开源框架中经常会遇到,比如tomcat中filter,dubbo中的filter.那么它的作用是将请求和返回进行解耦。比如一个请求过来了,先传给A进行处理,再传给B进行处理,再传给C进行处理,一条链路下来。
public class TestChain {
public static void main(String[] args) {
FileChain fileChain = new FileChain();
fileChain.addhandler(new LogHandler());
fileChain.addhandler(new UnicodeHandler());
fileChain.handle();
}
}
abstract class Handler {
protected Handler succedor = null;
public void handle() {
doHandle();
if (succedor != null) {
succedor.handle();
}
}
public void setHandler(Handler handler) {
this.succedor = handler;
}
abstract void doHandle();
}
class LogHandler extends Handler {
@Override
void doHandle() {
System.out.println("add log");
}
}
class UnicodeHandler extends Handler {
@Override
void doHandle() {
System.out.println("translate unicode");
}
}
class FileChain {
//链表维护调用链
private Handler head = null;
private Handler tail = null;
public void addhandler(Handler handler) {
if (head == null) {
head = handler;
tail = handler;
} else {
tail.setHandler(handler);
tail = handler;
}
}
public void handle() {
if (head != null) {
head.handle();
}
}
}
状态模式
状态机一般用于状态转换,当处于某种状态下,其他操作应该有什么其他状态。比如打王者荣耀时,当碰到甄姬的溜溜球的时候,如果你的状态处于被溜溜球已经处于第二次的状态,则状态应该被冻住,同时发出冻住的声音,如果你的状态属于第一次的时候,则标记为两次被打中,发出打中声音。在这个过程只涉及状态更改,不涉及补偿状态等。状态机一般有三个部分组成:状态,事件,动作。事件也称转移条件。接下来这个例子,我找了文档上的一段说明。
public class TestState {
public static void main(String[] args) {
MarioMachine marioMachine = new MarioMachine();
System.out.println(marioMachine.getScore()+"--"+marioMachine.getCurrentState().getName());
marioMachine.obtainMushRoom();
System.out.println(marioMachine.getScore()+"--"+marioMachine.getCurrentState().getName());
}
}
enum State {
SMALL("small"),
SUPER("super");
private String type;
private State(String type) {
this.type = type;
}
}
class MarioMachine {
private int score;
private IMario currentState;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public MarioMachine() {
this.score = 0;
this.currentState = SmallMario.instance;
}
public void setCurrentState(IMario mario){
this.currentState = mario;
}
public IMario getCurrentState() {
return currentState;
}
public void obtainMushRoom(){
this.currentState.obtainMushRoom(this);
}
}
interface IMario {
State getName();
void obtainMushRoom(MarioMachine stateMachine);
void meetMonster(MarioMachine stateMachine);
}
class SmallMario implements IMario {
public static final SmallMario instance = new SmallMario();
@Override
public State getName() {
return State.SMALL;
}
@Override
public void obtainMushRoom(MarioMachine stateMachine) {
stateMachine.setCurrentState(SupperMario.instance);
stateMachine.setScore(stateMachine.getScore()+100);
}
@Override
public void meetMonster(MarioMachine stateMachine) {
stateMachine.setCurrentState(null);
stateMachine.setScore(0);
}
}
class SupperMario implements IMario{
public static final SupperMario instance = new SupperMario();
@Override
public State getName() {
return State.SUPER;
}
@Override
public void obtainMushRoom(MarioMachine stateMachine) {
stateMachine.setCurrentState(SupperMario.instance);
stateMachine.setScore(stateMachine.getScore()+1000);
}
@Override
public void meetMonster(MarioMachine stateMachine) {
stateMachine.setCurrentState(SmallMario.instance);
stateMachine.setScore(stateMachine.getScore()+1000);
}
}
迭代器模式
迭代器模式我们其实在集合遍历的时候一直在使用。那么它和for 有什么区别呢,在数组,链表的迭代中差别不是很明显,但是像在图等复杂模型中,拥有更快捷的便利。
public class TestIterator {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("a");
list.add("n");
list.add("b");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String value = iterator.next();
iterator.remove();
System.out.println(value);
}
System.out.println(list.size());
}
}
访问者模式
访问者模式我们通过在asm中用的最多。作用于将业务数据和业务操作分开。
public class TestExtractor {
public static void main(String[] args){
Extractor extractor = new Extractor();
extractor.extract(new PDFFile());
}
}
class Extractor{
public void extract(ResourceFile resourceFile){
System.out.println("extract file"+resourceFile.name());
System.out.println("the text "+resourceFile.context());
}
}
interface ResourceFile{
String name();
String context();
}
class PDFFile implements ResourceFile{
@Override
public String name() {
return "PDF";
}
@Override
public String context() {
return "this is text";
}
}
备忘录模式
备忘录模式通过一个单独的类或者其他的形式,将对象进行备份和恢复。
public class TestMemoto {
public static void main(String[] args) {
InputText text = new InputText();
InputHolder inputHolder = new InputHolder();
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String input = scanner.next();
if (input.equals(":list")) {
System.out.println(text.getText());
} else if (input.equals(":undo")) {
InputText snapshot = inputHolder.popSnapshot();
text.setText(snapshot.getText());
} else {
inputHolder.stashSnapshot(text);
text.append(input);
System.out.println("----");
}
}
}
}
class InputText {
StringBuilder consoleText = new StringBuilder();
public void setText(String text) {
consoleText.replace(0, consoleText.length(), text);
}
public String getText() {
return consoleText.toString();
}
public void append(String textStr) {
consoleText.append(textStr);
}
}
class InputHolder {
private Stack<InputText> stack = new Stack<InputText>();
public InputText popSnapshot() {
return stack.pop();
}
public void stashSnapshot(InputText inputText) {
InputText deepCopyInputText = new InputText();
deepCopyInputText.append(inputText.getText());
stack.push(deepCopyInputText);
}
}
命令模式
命令模式和策略模式非常像。但是在使用上会有不同。策略模式时根据不同的策略选择不同的实现,但是目的都是一致的。命令模式是将请求封装成命令,进行执行。
解释器模式
解释器为了某种语言定义了它的语法,并通过解释器来处理这种语法。
中介者模式
中介者模式是当对象进行复杂交互时,通过中介类进行管理
以上就是设计模式中的行为型,基本上23种设计模式都讲完了,有些不理解的也按照demo敲了一遍,值得反复推敲。希望在以后阅读源码和自己设计的时候,能够熟练于心。