6大设计原则:

1. 单一职责原则

单一职责原则的英文名称是 Single Responsibility Principle ,简称是SRP(There should never be more than one reason for a class to change.)
见名知意,充斥着满满的争议,需求的更替,版本的迭代,场景的复杂,种种都能导致这个被破坏,但是把出发点是好的,单一意味着简单,简单意味着易懂,而后易维护、节省人力、成本、增加稳定性;但是场景复杂时就类就多了,em...;仁者见仁智者见智,不展开讲了

2. 里氏替换原则

里氏替换原则( Liskov Substitution Principle, LSP )
定义1:

If for each object o1 of type S there is an object o2 of
type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is
substituted for o2 then S is a subtype of T. (如果对每一个类型为 S 的对象 o1 ,都有类型为 T 的对
象 o2 ,使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变
化,那么类型 S 是类型 T 的子类型。)
定义2:
Functions that use pointers or references to base classes must be able to use
objects of derived classes without knowing it. (所有引用基类的地方必须能透明地使用其子类的
对象。)
说的就是Java中父子关系(继承、实现),父类出现的地方,可替换成子类
原则上相当于制定了契约
正例不举了,我举个反例吧:
如果其他程序调用时,不能通过父类或者接口,而必须使用子类时,则说明类的设计已经违背了LSP原则;
public interface A {void method();
}public class AImpl implements A {public void method() {}public void methodSub() {}
}// 使用方public class Test {public static void main(String[] args) {AImpl obj = new AImpl();// 外部调用时obj对象的类不能替换成A,则违反了LSPobj.methodSub();}
}

3. 依赖倒置原则

依赖倒置原则( Dependence Inversion Principle,DIP )
High level modules should not depend upon low level modules.Both should depend upon
abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.
  • 模块间的依赖通过抽象发生(接口或抽象类)
  • 接口或抽象类不依赖于实现类
  • 实现类依赖接口或抽象类
简而言之就是解耦

4. 接口隔离原则

Interface Segregation Principle

  • Clients should not be forced to depend upon interfaces that they don't use. (客户端不应该依
    赖它不需要的接口。)
  • The dependency of one class to another one should depend on the smallest possible interface. (类间的依赖关系应该建立在最小的接口上。)
简而言之,用什么依赖什么
所以对接口就要求
  • 接口职能单一,服务定制,设计有度
  • 接口要高内聚,减少交互

5. 迪米特法则

迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge Principle,LKP)
只通过接口协定交互,其他一概不管;Only talk to your immediate friends(只与直接的朋友沟通。)
是自己的逻辑就是自己的逻辑,不是自己的就不是自己的

6. 开闭原则

Open Closed Principle
Software entities like classes,modules and functions should be open for extension but closed for
modifications. (一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。)
开闭原则个人粗浅的见解是一个法典,像一种理想化,一种指导方针;我们需要通过抽象约束、规范制度、需求预见等使程序在时间推移的过程中一直在做扩展和增强,减少已有的抽象的修改(例如接口制定了,以后都不用再修改,这个肯定是我们最希望的);我们需要朝这个方向去努力,拥抱变化的同时,越少打破这个原则

28大设计模式

1. 单例模式

最简单常用的模式,不展开了

public Sun {private static final Sun sun = new Sun();public static Sun getInstance() {return sun;}public void light() {System.out.println("太阳发光");}
}

2. 工厂方法模式

Define an interface for creating an object,but let subclasses decide which class to
instantiate.Factory Method lets a class defer instantiation to subclasses. (定义一个用于创建对象的
接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
优点:
1.  良好的封装性,代码结构清晰
2. 良好的扩展性(横向扩展,例如例子中需要新增一种食物)
3. 解耦,散落到各处的类似的初始化逻辑可以被封装,不用重复写,也提高维护性
应用:
1. 可简化成 简单工厂模式 用静态方法代替工厂类
2. 升级成多工厂
3. 单例模式的替代品
4. 延迟初始化
public interface Food {void name();
}public class Bread implements Food {@Overridepublic void name() {System.out.println("我是面包");}
}public class Cookie implements Food {@Overridepublic void name() {System.out.println("我是饼干");}
}public class FoodFactory {public <T extends Food> T productFood(Class<T> cls) {T t = null;try {t = cls.newInstance();} catch (Exception e) {System.out.println("我不会生产这个");e.printStackTrace();}return t;}public static void main(String[] args) {FoodFactory factory = new FoodFactory();Bread bread = factory.productFood(Bread.class);bread.name();Cookie cookie = factory.productFood(Cookie.class);cookie.name();}
}

3. 抽象工厂模式

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们 的具体类。)

优点:
1. 抽象封装
2. 分类约束
缺陷:
1. 子工厂扩展受限
public interface Food {void name();
}public class SweetBread implements Food {@Overridepublic void name() {System.out.println("我是甜面包");}
}public class SaltyBread implements Food {@Overridepublic void name() {System.out.println("我是咸面包");}
}public class Cookie implements Food {@Overridepublic void name() {System.out.println("我是饼干");}
}public abstract class FoodFactory {<T extends Bread> T productFood(Class<T> cls);
}public class BreadFactory extends FoodFactory {public <T extends Bread> T productFood(Class<T> cls) {T t = null;try {t = cls.newInstance();} catch (Exception e) {System.out.println("我不会生产这个");e.printStackTrace();}return t;}public static void main(String[] args) {FoodFactory factory = new BreadFactory();SweetBread bread1 = factory.productFood(SweetBread.class);bread1.name();SaltyBread bread2 = factory.productFood(SaltyBread.class);cookie2.name();}
}

4. 模板方法模式

对于业务模型的业务动作模板化;基本方法在子类中实现,模板方法在父类中调度

优点:
1. 封装固定部分,扩展可变部分
2. 公共代码提取,统一行为控制
缺陷:
1. 行为流程固化(之前是抽象的是一个动作;现在是抽象了动作和动作的顺序)
2. 复杂场景新手阅读不适(串联逻辑时,一下到子类,一下到父类,绕晕)
public abstract class Car {public abstract void start();public abstract void drive();public abstract void stop();public void run() {start();drive();stop();}
}
public class HongQiCar extends Car {@Overridepublic void start() {System.out.println("红旗车启动");}@Overridepublic void drive() {System.out.println("红旗车行驶");}@Overridepublic void stop() {System.out.println("红旗车停止");}public static void main(String[] args) {Car car = new HongQiCar();car.run();}
}

5. 建造者模式

建造者模式(Builder Pattern)也叫做生成器模式

Separate the construction of a complex object from its representation so that the same
construction process can create different representations. (将一个复杂对象的构建与它的表示分
离,使得同样的构建过程可以创建不同的表示。)
优点:
良好的封装性和抽象
易于扩展
和工厂模式类似都是在创建类实例,但是不同的是,建造者开放了一部分流程给外部定制化
public abstract class CarModel {/*** 装备顺序*/private ArrayList<String> sequence = new ArrayList<String>();/*** 发动*/public abstract void engine();/*** 喇叭*/public abstract void horn();/*** 挂挡*/public abstract void gearbox();/*** 加油*/public abstract void gas();/*** 停车*/public abstract void stop();/*** 介绍*/public void drive() {for (String step : sequence) {if ("engine".equals(step)) {engine();} else if ("horn".equals(step)) {horn();} else if ("gearbox".equals(step)) {gearbox();} else if ("gas".equals(step)) {gas();} else if ("stop".equals(step)) {stop();}}}/*** 设置装配顺序*/public void setSequence(ArrayList<String> sequence) {this.sequence = sequence;}
}
public abstract class CarBuilder {// 顺序public abstract void setSequence(ArrayList<String> sequence);// 设置顺序后,获取模型public abstract CarModel getCarModel();
}
public class HongqiCarModel extends CarModel {@Overridepublic void engine() {System.out.println("红旗车无钥匙启动汽车");}@Overridepublic void horn() {System.out.println("红旗车按响喇叭");}@Overridepublic void gearbox() {System.out.println("红旗车挂前进挡");}@Overridepublic void gas() {System.out.println("红旗车加速");}@Overridepublic void stop() {System.out.println("红旗车刹车停车");}
}
public class HoneqiCarBuilder extends CarBuilder {private HongqiCarModel carModel = new HongqiCarModel();@Overridepublic void setSequence(ArrayList<String> sequence) {carModel.setSequence(sequence);}@Overridepublic CarModel getCarModel() {return carModel;}public static void main(String[] args) {}
}
public class HongqiDirector {private HoneqiCarBuilder honeqiCarBuilder = new HoneqiCarBuilder();/*** A型号车需要先鸣笛才能开* @return*/public HongqiCarModel getHongqiModelA() {ArrayList<String> sequence = new ArrayList<>();sequence.add("horn");sequence.add("engine");sequence.add("gearbox");sequence.add("gas");sequence.add("stop");HoneqiCarBuilder builder = new HoneqiCarBuilder();builder.setSequence(sequence);return (HongqiCarModel) builder.getCarModel();}/*** A型号车不需要先鸣笛能开* @return*/public HongqiCarModel getHongqiModelB() {ArrayList<String> sequence = new ArrayList<>();sequence.add("engine");sequence.add("gearbox");sequence.add("gas");sequence.add("stop");HoneqiCarBuilder builder = new HoneqiCarBuilder();builder.setSequence(sequence);return (HongqiCarModel) builder.getCarModel();}
}

6. 代理模式

代理模式(Proxy Pattern)
Provide a surrogate or placeholder for another object to control access to it. (为其他对象提供
一种代理以控制对这个对象的访问。)
优点:
  • 高扩展性,不侵入实现层的源码
  • 职能清晰
public interface ITask {void doJob();
}
public class TaskImpl implements ITask {@Overridepublic void doJob() {System.out.println("doing job");}
}
// 动态代理
public class DynamicProxy implements InvocationHandler {private Object object;public DynamicProxy(Object object) {this.object = object;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("before do job...");Object result = method.invoke(object, args);System.out.println("after do job...");return result;}
}
// 静态代理
public class StaticProxy implements ITask {private ITask task;public StaticProxy(final ITask task) {this.task = task;}@Overridepublic void doJob() {System.out.println("before do job...");task.doJob();System.out.println("after do job...");}
}
public class TestProxy {public static void main(String[] args){ITask task = new TaskImpl();StaticProxy p1 = new StaticProxy(task);task.doJob();System.out.println("********************************");p1.doJob();System.out.println("********************************");ITask dynamic = (ITask)Proxy.newProxyInstance(ITask.class.getClassLoader(), task.getClass().getInterfaces(), new DynamicProxy(task));dynamic.doJob();}
}

Java中有JDK动态代理和cglib动态代理,可自行研究;动态代理是非常常见和使用的设计模式,对于业务前后统一的处理都可使用此模式;也叫AOP(Aspect Oriented Programming面向切面编程)

7. 原型模式

原型模式(Prototype Pattern )
Specify the kinds of objects to create using a prototypical instance,and create new objects by
copying this prototype. (用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对
象。)
原型模式的核心是一个 clone 方法,通过该方法进行对象的拷贝, Java 提供了一个Cloneable 接口来标示这个对象是可拷贝的
优点:
  • 对于构造函数消耗的性能非常多且实例化的内容是一致的对象能够大幅提高性能
  • 双刃剑:逃避构造函数约束(成也萧何,败也萧何,千万注意此点对业务的影响)

缺点:

  • 仅深拷贝本对象(属性如果是对象则为浅拷贝)
  • clone和final一山不容二虎,成员变量加final后直接编译报错
public class Thing implements Cloneable {private ArrayList<String> arrayList = new ArrayList<String>();@Overridepublic Thing clone() {Thing thing = null;try {thing = (Thing) super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return thing;}public void setValue(String value) {this.arrayList.add(value);}public ArrayList<String> getValue() {return this.arrayList;}
}
public class Test {public static void main(String[] args) {Thing t = new Thing();// 仅深拷贝当前对象,内部的List为浅拷贝Thing clone = t.clone();}
}

8. 中介者模式

Define an object that encapsulates how a set of objects
interact.Mediator promotes loose coupling by keeping objects from referring to each other
explicitly,and it lets you vary their interaction independently. (用一个中介对象封装一系列的对象
交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它
们之间的交互。)
优点:
减少类间关系,从一对多编程一对一
缺点:
中介类肿胀
例如MVC的Controller层就属于中介者模式

9. 命令模式

命令模式是一个高内聚的模式
Encapsulate a request as an object,thereby
letting you parameterize clients with different requests,queue or log requests,and support undoable operations.(将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。)
优点:
类间解耦
可扩展性
缺点:
Command子类会非常多,这个类非肿胀
public abstract class Receiver {public abstract void doSomething();
}
public class ReceiverImpl1 extends Receiver {@Overridepublic void doSomething() {System.out.println("On my building");}
}
public class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void action() {this.command.execute();}
}
public abstract class Command {public abstract void execute();
}
public class CommandImpl1 extends Command {private Receiver receiver;public CommandImpl1(Receiver receiver) {this.receiver = receiver;}public void execute() {this.receiver.doSomething();}
}
public class Test {public static void main(String[] args) {Invoker invoker = new Invoker();// 定义接收者Receiver receiver = new ReceiverImpl1();// 定义一个发送给接收者的命令Command command = new CommandImpl1(receiver);// 把命令交给调用者去执行invoker.setCommand(command); invoker.action();}
}

10. 责任链模式

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to
handle the request.Chain the receiving objects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。)
优点:
解耦,(请求和处理分开)
缺点:
“太解耦”,链路太长时,性能差且不好阅读和排查问题

11. 装饰模式

装饰模式( Decorator Pattern )
优点:
  • 装饰类和被装饰类可以独立发展,而不会相互耦合。
  • 装饰模式是继承关系的一个替代方案
  • 动态扩展类的功能

缺点:

  • 不要套太多,套娃太深,复杂度太高,排查和理解耗时
public class Decoratee {public Decoratee() {whatIHave = new ArrayList<>();whatIHave.add("锦");whatIHave();}private List<String> whatIHave;public void gain(String str) {whatIHave.add(str);}public void whatIHave() {if(whatIHave.size() == 0) {System.out.println("我什么都没有!!!");} else {System.out.print("我有");for(String have : whatIHave) {System.out.print(have+" ");}System.out.println();}}
}
public class Decorator {private Decoratee decoratee;public Decorator(Decoratee decoratee) {this.decoratee = decoratee;}public void decorate() {decoratee.gain("花");decoratee.whatIHave();}public static void main(String[] args){Decorator decorator = new Decorator(new Decoratee());decorator.decorate();}
}

12. 策略模式

策略模式(Strategy Pattern )
Define a family of algorithms,encapsulate each one,and make them interchangeable. (定义一组
算法,将每个算法都封装起来,并且使它们之间可以互换。)
优点:
  • 策略自由切换,方便横向扩展
  • 避免多重条件判断

缺点:

  • 策略类数量多时,需要有诸葛亮一样的人来运筹帷幄,复用性也低
  • 所有策略都得对外暴露
public interface AttackStrategy {/*** 五行法术攻击*/void fiveElementsMagicAttack();
}
public class AttackStrategyGold implements AttackStrategy {@Overridepublic void fiveElementsMagicAttack() {System.out.println("使用金系法术攻击");}
}
public class AttackStrategyWood implements AttackStrategy {@Overridepublic void fiveElementsMagicAttack() {System.out.println("使用木系法术攻击");}
}
public class AttackStrategyWater implements AttackStrategy {@Overridepublic void fiveElementsMagicAttack() {System.out.println("使用水系法术攻击");}
}
public class AttackStrategyFire implements AttackStrategy {@Overridepublic void fiveElementsMagicAttack() {System.out.println("使用火系法术攻击");}
}
public class AttackStrategySoil implements AttackStrategy {@Overridepublic void fiveElementsMagicAttack() {System.out.println("使用土系法术攻击");}
}
public class Context {AttackStrategy attackStrategy;public Context(AttackStrategy attackStrategy) {this.attackStrategy = attackStrategy;System.out.println("指挥部制定攻击策略");}public AttackStrategy getAttackStrategy() {return attackStrategy;}
}
public class Battle {public static String[] enemy = {"金系敌人", "木系敌人", "水系敌人", "火系敌人", "土系敌人"};public static void main(String[] args) {for (int i=0; i<5; i++) {System.out.println("---------------------------");attack();}}private static void attack() {int idx = (int)(Math.random() * 5);Context headquarters;System.out.println("我方遭遇:" + enemy[idx]);switch (enemy[idx]) {case "金系敌人":headquarters = new Context(new AttackStrategyFire());break;case "木系敌人":headquarters = new Context(new AttackStrategyGold());break;case "水系敌人":headquarters = new Context(new AttackStrategySoil());break;case "火系敌人":headquarters = new Context(new AttackStrategyWater());break;case "土系敌人":headquarters = new Context(new AttackStrategyWood());break;default:headquarters = new Context(new AttackStrategyGold());}headquarters.getAttackStrategy().fiveElementsMagicAttack();}
}

13. 适配器模式

适配器模式( Adapter Pattern )
Convert the interface of a class into another interface clients expect.Adapter lets classes work
together that couldn't otherwise because of incompatible interfaces. (将一个类的接口变换成客户
端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工
作。)

适配器模式又叫做变压器模式,也叫做包装模式( Wrapper ),但是包装模式可不止一
优点:
  • 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定 他们就成
  • 降低了类的存在感,简化使用
  • 提供类的复用和灵活性

缺点:

  • 个人人为也不算缺点吧,项目初期不用考虑这个模式,大多在维护阶段去使用,去适配未知的场景(就像在中国是220的电,做的充电器就按220的做,以后去了未知的地区,再考虑做新的,因为电压,插口大小都是未知的)
  • 而且是不符合原有设计的时候才会发生,使用此改造也可能代码比较大的改造量
public interface DC5V {int outDC5v();
}public class ChargeAdapter extends AC220V implements DC5V {@Overridepublic int outDC5v() {int i = outAC220v();i = i / 44;System.out.println("转换成"+i+"V直流电!");return i;}
}public class AC220V {int outAC220v() {int v = 220;System.out.println("输出220v交流电!!!");return v;}
}public class Mobile {void charge(DC5V charger) {int i = charger.outDC5v();System.out.println("charging...");}public static void main(String[] args) {Mobile mobile = new Mobile();mobile.charge(new ChargeAdapter());}
}

14. 迭代器模式

迭代器模式(Iterator Pattern )目前已经是一个没落的模式,基本上没人会单独写一个迭
代器
Provide a way to access the elements of an aggregate object sequentially without exposing its
underlying representation. (它提供一种方法访问一个容器对象中各个元素,而又不需暴露该
对象的内部细节。)
public interface Iterator {//遍历到下一个元素 public Object next(); //是否已经遍历到尾部 public boolean hasNext(); //删除当前指向的元素 public boolean remove();
}

Java本身已经提供了很强大的基础API,所以我们基本不需要自己再去写这些

15. 组合模式

组合模式 (Composite Pattern) 也叫合成模式,有时又叫做部分 -整体模式(Part-Whole),主要是用来描述部分与整体的关系
Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.(将对象组合成树形结构以表示 “ 部分 - 整体 ” 的层次结构,使得用户对单个对象和组合对象的使用具有一致性。)
优点:
1. 整体部分调用简单
2. 部分增加自由
缺点:
1. 部分没有定义,直接使用了实现类(对于面向接口编程的理念是不一致的,与依赖导致原则冲突)
使用场景
1. 维护部分和整体的关系,树形菜单、目录结构、组织架构
2. 从一个整体中能独立出去的部分

16. 观察者模式

观察者模式( Observer Pattern)也叫做发布订阅模式(Publish/subscribe ) ,它是一个在项 目中经常使用的模式
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每 当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。)
几个主要的组成部分
1. 被观察者
定义被观察者,和主要的动作
2. 观察者
定义观察者收到消息后的动作
3. 具体的被观察者
具体的被观察动作
4. 具体的观察者
具体的观察者动作
/*** 被观察者*/
public interface Observable {// 增加一个观察者void addObserver(Observer observer);// 删除一个观察者void deleteObserver(Observer observer);// 既然要观察,我发生改变了他也应该有所动作,通知观察者void notifyObservers(String context);
}/*** 观察者*/
public interface Observer {void action(String info);
}/*** 具体的被观察对象*/
public class Student implements Observable {private String name;public Student(String name) {this.name = name;}private List<Observer> observers = new ArrayList<>();@Overridepublic void addObserver(Observer observer) {observers.add(observer);}@Overridepublic void deleteObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(String context) {for (Observer observer : observers) {observer.action(context);}}public void quWangBa() {System.out.println(name + "去网吧");notifyObservers(name + "去网吧");}
}/*** 具体的建观察者*/
public class Father implements Observer {@Overridepublic void action(String info) {System.out.println("由于" + info + "被父亲知道,父亲教了他一套军体拳");}
}/*** 具体的观察者*/
public class Teacher implements Observer {@Overridepublic void action(String info) {System.out.println("由于" + info + "被老师知道,老师要求其写检讨,并通报批评");}
}public class Client {public static void main(String[] args) {Father father = new Father();Teacher teacher = new Teacher();Student student = new Student("张三");student.addObserver(teacher);student.addObserver(father);student.quWangBa();}
}

17. 门面模式

门面模式(Facade Pattern)也叫做外观模式,是一种比较常用的封装模式,其定义如
下:
Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level
interface that makes the subsystem easier to use.(要求一个子系统的外部与其内部的通信必须通
过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。)

个人理解门面模式是定义一个统一的规范,不论用什么方式实现,出入的“门面”是固定的,且不暴露门面内部的逻辑

public class Facade {private Worker worker = new Worker();public void doSomething() {// 对外暴露的方法固定,内部的实现目前是工人1去做,后续需要调整可以是其他的工人去做worker.doSomething();}
}public class Worker {public void doSomething() {}
}

优点:

1. 减少系统的互相依赖

2. 提高门面内部的灵活性和自主性

3. 提高安全性(这个其实也是减少互相依赖带来的好处,减少了代码的侵入)

缺点:

不符合开闭原则,对修改关闭,对扩展开放,facade类定义好后,出现问题的话,唯一能做的一件事就是修改门面代码,这会影响所有人,所以很多时候,在门面对于一部分场景正确,但对一部分场景错误时,经常会开“后门”,再开一扇门,搞的次数多了,越来越复杂,越来越难以理解,越来越难维护。

门面如果能让优秀的人定义好的话,可以减少低水平开发人员对系统冲击,最差就是将其实现的代码重写,不会对整体造成影响;正如缺点中讲的,也是双刃剑,慎之又慎。

18. 备忘录模式

备忘录模式( Memento Pattern )提供了一种弥补真实世界缺陷的方法,让 “ 后悔药 ” 在程
序的世界中真实可行,其定义如下:
Without violating encapsulation,capture and externalize an object's internal state so that the
object can be restored to this state later. (在不破坏封装性的前提下,捕获一个对象的内部状
态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。)

备忘录就像我们处理数据库事务一样,可以对操作进行回滚

public class Originator {private String state;public String getState() {return state;}public void setState(String state) {this.state = state;}public Memento createMemento() {return new Memento(this.state);}public void restoreMemento(Memento memento) {this.state = memento.getState();}public static void main(String[] args) {Caretaker caretaker = new Caretaker();Originator originator = new Originator();originator.setState("小明正在写PPT");System.out.println("老板让小明去接待客户");System.out.println("小明先记录备忘录");caretaker.setMemento(originator.createMemento());originator.setState("小明正在接待客户");System.out.println("小明接待完客户,继续去写PPT");originator.restoreMemento(caretaker.getMemento());System.out.println(originator.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 getMemento() {return memento;}public void setMemento(Memento memento) {this.memento = memento;}
}

应用场景

  • 保存恢复数据的场景
  • 数据旁路处理的场景
  • 实际应用过程大多会进行变形,所以其实没有很标准的落地形式,算一种抽象定义

注意点

  • 备忘录的生命周期管理,防止出现内存泄漏,业务脏数据等问题
  • 备忘录创建的性能问题,大量且频繁创建销毁,要考虑内存和CPU的消耗
  • 单纯的整对象备份,可以用Cloneable代替Memento类

大话西游中,周星驰在洞口月光下对着月光宝盒大喊“波若波若蜜”,来回穿梭时光回去救白晶晶,结果频繁操作,旁边的观察者吴孟达一脸懵逼,然后程序不稳定,穿越回了500年前...

18. 访问者模式

访问者模式( Visitor Pattern )是一个相对简单的模式,其定义如下: Represent an
operation to be performed on the elements of an object structure. Visitor lets you define a new
operation without changing the classes of the elements on which it operates. (封装一些作用于某种
数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的
操作。)
public abstract class Element {// 定义业务逻辑public abstract void doSomething();// 允许谁来访问public abstract void accept(IVisitor visitor);
}public class ConcreteElement1 extends Element {// 完善业务逻辑public void doSomething() {// 业务处理}// 允许那个访问者访问public void accept(IVisitor visitor) {visitor.visit(this);}
}public class ConcreteElement2 extends Element {// 完善业务逻辑public void doSomething() {// 业务处理}// 允许那个访问者访问public void accept(IVisitor visitor) {visitor.visit(this);}
}public interface IVisitor {// 可以访问哪些对象void visit(ConcreteElement1 el1);void visit(ConcreteElement2 el2);
}public class Visitor implements IVisitor {// 访问el1元素public void visit(ConcreteElement1 el1) {el1.doSomething();}// 访问el2元素public void visit(ConcreteElement2 el2) {el2.doSomething();}
}public class Client {public static void main(String[] args) {for (int i = 0; i < 10; i++) {// 获得元素对象Element el = createElement();// 接受访问者访问el.accept(new Visitor());}}public static Element createElement() {Random rand = new Random();if (rand.nextInt(100) > 50) {return new ConcreteElement1();} else {return new ConcreteElement2();}}
}

优点:

  • 符合单一职责原则
  • 可扩展性
  • 灵活性

缺点:

  • 违背依赖倒置原则(访问者依赖具体元素,而非抽象元素),很多时候我们在设计开发时会说,不是抽象的,那我抽象不就行了,但除了从代码上是抽象类或者接口,业务上真的是抽象的吗?我们口中的抽象真的是抽象吗?
  • 维护麻烦,对于元素增加、修改、删除都是麻烦事
未完待续...

-- 有缘登山,寒山不寒

Java 6大设计原则28大设计模式相关推荐

  1. 设计模式01-七大设计原则

    设计模式01-七大设计原则 文章目录 设计模式01-七大设计原则 开闭原则-Open Close 依赖倒置原则-Dependence Inversion 单一职责原则-Simple ResponsiB ...

  2. Java设计模式GOF之6大设计原则

    Java设计模式GOF之6大设计原则原则 1.开闭原则(Open Close Principle) 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 开闭原则是面向对象的可复用设计的第一块基石 ...

  3. Java架构师必须知道的 6 大设计原则

    转载自   Java架构师必须知道的 6 大设计原则 在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义.本文主要将总结这些常见 ...

  4. 设计模式 — 6大设计原则(依赖倒置和接口隔离原则)

    设计模式 依赖倒置原则 示例 一 示例 二 依赖的三种写法 总结 接口隔离原则 实例 一 总结 依赖倒置原则 依赖倒置原则(Dependence Inversion Principle,DIP)这个名 ...

  5. 设计模式概述—6大设计原则

    第一部分:6大设计原则 六大设计原则: 1)Single Responsibility Principle:单一职责原则 2)Open Closed Principle:开闭原则 3)Liskov S ...

  6. C++ 设计模式(8大设计原则、23种设计模式)李建忠

    简 述: 设计模式,久闻大名.此记录学习 "C++ 设计模式 李建忠" 的札记,核心共 8大设计原则.23中设计模式.后发现 GitHub 也有类似笔记 Ref1 .Ref2 相关 ...

  7. 设计模式之禅《一》 大旗不挥,谁敢冲锋 ——6大设计原则

    设计模式之禅<一>大旗不挥,谁敢冲锋 --6大设计原则 <一> 六大原则 一:单一职责原则 1.单一职责原则最难划分的就是职责 2.有两个可以变化的原因放到了一个接口中,这就为 ...

  8. 架构设计模式—6大设计原则

    架构设计原则 6大设计原则 Single Responsibility Principle : 单一职责原则 Liskov Substitution Principle : 里氏替换原则 Depend ...

  9. 面向对象设计原则_聊聊面向对象的6大设计原则

    程序员都知道编程有 3 大类:面向过程.面向对象.面向函数.面向对象是被讨论的最多的,个人认为,这是因为 Java 之类的编程语言有强大的用户基础,本质还是因为比较符合人的直觉. 说到面向对象,大家可 ...

最新文章

  1. 解决mac上mariadb不能远程访问的问题
  2. 用python画烟花-python实现烟花小程序
  3. android 水平方向瀑布流,Android RecyclerView(瀑布流)水平/垂直方向分割线
  4. 物化视图 sql server 1
  5. 特斯拉全球超级充电站已超过25000座 国内超过870座
  6. 受疫情影响 MWC 2020正式取消
  7. 51单片机 | 基于I2C总线的秒表模拟应用
  8. aws lam nodejs mysql_NodeJs IF Statement in AWS Lambda using MySQL database
  9. Oracle(7)——Oracle修改国家字符集
  10. 直播app服务器部署,直播视频服务器的选择!
  11. Redis 6 入门到入坟 详细教程 @学习笔记
  12. win11更新后任务栏空白怎么办? win11更新后任务栏空白卡死的解决方法
  13. 解决百度云下载缓慢问题
  14. golang cpuprofile分析
  15. 玩转Qml(18)-用户向导
  16. 利用 css 和 html 实现简单的双心
  17. 【JavaWeb】JSP(172-190)
  18. 在阿里这六年,我学到的所有东西都在这了
  19. Excel如何制作工资表
  20. Python实现的免费pdf阅读器

热门文章

  1. 比北漂更苦的,是我们“双色青年”
  2. 三方直播SDK对比(腾讯云,阿里云,网易云信,七牛云,金山云,声网,即构科技)
  3. JSP运行原理及运行过程
  4. 【English】一月英语
  5. 缩印技巧你知多少?缩印怎么设置?
  6. 一种输电线路视频图像在线监测装置
  7. php ci框架开发手册下载,php敏捷开发codeigniter框架-CodeIgniter教程(中文手册)pdf格式免费完整版-东坡下载...
  8. 使用ASP.NET Core进行跨平台Web文档扫描
  9. html控制智能家居,一种基于数据库中间件和HTML5的智能家居控制软件系统
  10. 2016第19本:至关重要的关系