行为型
描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法和对象间职责的分配
模板方法模式
概述
定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变算法结构的情况下重新定义该算法的某些特定步骤
优缺点
优点:
- 封装了不变部分,扩展可变部分。即将不变部分分装到父类中,可变部分交由子类实现
- 提取了父类中公共的代码部分,实现了代码的复用
- 符合了开闭原则
缺点:
- 增加了类的个数,使得系统更加庞大
- 使用继承关系导致无法添加新的方法
实现
public abstract class AbstractTemplate {
/**
* 模板方法
*/
public void templateMethod(){
calcHeight();
calcWeight();
}
/**
* 具体方法
*/
public void calcHeight(){
System.out.println("计算身高");
}
/**
* 抽象方法,交由子类扩展
*/
public abstract void calcWeight();
}
/**
* 具体子类
*/
public class ConcreteTemplate extends AbstractTemplate{
@Override
public void calcWeight() {
System.out.println("子类实现计算体重");
}
}
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
AbstractTemplate template = new ConcreteTemplate();
template.templateMethod();
}
}
策略模式
概述
将一组算法封装到一系列的策略类里面,作为一个抽象策略类的子类。其重心是组织算法
优缺点
优点:
- 可以避免使用多重条件语句
- 可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的
- 提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法
- 把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离
缺点:
- 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
- 造成很多的策略类,增加维护难度。
实现
/**
* 抽象策略类
*/
public interface Strategy {
//抽象策略类
void operate();
}
/**
* 具体策略1
*/
public class StrategyImp1 implements Strategy {
@Override
public void operate() {
System.out.println("具体策略1");
}
}
/**
* 具体策略2
*/
public class StrategyImp2 implements Strategy {
@Override
public void operate() {
System.out.println("具体策略2");
}
}
/**
* 环境类,以供客户端使用
*/
public class Environment {
private Strategy strategy;
public void setStrategy(Strategy strategy){
this.strategy = strategy;
}
public void operate(){
strategy.operate();
}
}
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
Environment environment = new Environment();
environment.setStrategy(new StrategyImp1());
environment.operate();
environment.setStrategy(new StrategyImp2());
environment.operate();
}
}
责任链模式
概述
为避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
优缺点
优点:
- 降低了对象之间的耦合度
- 增强了系统的可扩展性
- 增强了给对象指派职责的灵活性
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点: - 不能保证每个请求一定被处理
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用
实现
/**
* 抽象日志类
*/
public abstract class AbstractLogger {
public static final Integer INFO = 1;
public static final Integer DEBUG = 2;
public static final Integer ERROR = 3;
protected Integer level;
// 下一个责任链地址
protected AbstractLogger nextLogger;
public void setNextLogger(AbstractLogger nextLogger){
this.nextLogger = nextLogger;
}
public void logMessage(Integer level,String message){
//判断当前日志级别是否小于设置的日志级别,小于等于则处理请求,大于则交由下一日志级别处理
if(this.level <= level){
write(message);
}
//判断是否存在下一日志级别
if(nextLogger != null){
nextLogger.logMessage(level,message);
}
}
public abstract void write(String message);
}
/**
* error级别日志
*/
public class ErrorLogger extends AbstractLogger{
public ErrorLogger(Integer level){
this.level = level;
}
@Override
public void write(String message) {
System.out.println("ErrorLogger:"+message);
}
}
/**
* debug级别日志
*/
public class DebugLogger extends AbstractLogger{
public DebugLogger(Integer level) {
this.level = level;
}
@Override
public void write(String message) {
System.out.println("DebugLogger:"+message);
}
}
/**
* info级别日志
*/
public class InfoLogger extends AbstractLogger{
public InfoLogger(Integer level) {
this.level = level;
}
@Override
public void write(String message) {
System.out.println("InfoLogger:"+message);
}
}
/**
* 日志工厂,这里使用工厂模式来获取日志对象
*/
public class LoggerFactory {
/**
* 获取日志
* @return
*/
public static AbstractLogger getLogger(){
ErrorLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
DebugLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);
InfoLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
errorLogger.setNextLogger(debugLogger);
debugLogger.setNextLogger(infoLogger);
return errorLogger;
}
}
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
AbstractLogger logger = LoggerFactory.getLogger();
logger.logMessage(AbstractLogger.INFO,"info message");
//logger.logMessage(AbstractLogger.ERROR,"error message");
logger.logMessage(AbstractLogger.DEBUG,"debug message");
}
}
观察者模式
概述
指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
优缺点
优点:
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
- 目标与观察者之间建立了一套触发机制
缺点:
- 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用
- 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
实现
public class Subject {
private List<Observer> observers = new ArrayList<>();
private Integer state;
public Integer getState(){
return state;
}
public void attach(Observer observer){
observers.add(observer);
}
public void setState(Integer state){
this.state = state;
notifyAllObservers();
}
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
/**
* 观察者抽象类
*/
public abstract class Observer {
protected Subject subject;
public abstract void update() ;
}
public class ChildrenObserver extends Observer{
public ChildrenObserver(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("ChildrenObserver:"+subject.getState());
}
}
public class ChildrenObserver2 extends Observer{
public ChildrenObserver2(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Children2Observer:"+subject.getState());
}
}
public class ChildrenObserver3 extends Observer{
public ChildrenObserver3(Subject subject){
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update() {
System.out.println("Children2Observer:"+subject.getState());
}
}
public class Client {
public static void main(String[] args) {
Subject subject = new Subject();
new ChildrenObserver(subject);
new ChildrenObserver2(subject);
new ChildrenObserver3(subject);
subject.setState(12);
System.out.println("-------------");
subject.setState(15);
}
}
迭代器模式
概述
提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示
优缺点
优点:
- 无需暴露内部标识就可访问
- 遍历任务交由迭代器完成,简化了聚合类,且封装性良好
缺点:
- 增加了类的个数,这在一定程度上增加了系统的复杂性
实现
/**
* 迭代器接口
* @param <T>
*/
public interface Iterator<T> {
boolean hasNext();
T next();
}
public interface Container {
Iterator getIterator();
}
public class NameRepository implements Container{
private String[] names;
public NameRepository(String[] names){
this.names = names;
}
@Override
public Iterator getIterator() {
return new NameIterator();
}
/**
* 内部迭代器实现类
*/
private class NameIterator implements Iterator<String>{
int index;
@Override
public boolean hasNext() {
return index < names.length;
}
@Override
public String next() {
if(this.hasNext()){
return names[index++];
}
return null;
}
}
}
public class Client {
public static void main(String[] args) {
String[] names = {"Robert" , "John" ,"Julie" , "Lora"};
NameRepository nameRepository = new NameRepository(names);
Iterator iterator = nameRepository.getIterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}