一、Java基础
1、封装
良好的封装能够减少耦合
类内部的实现可以自由的修改
类具有清晰的对外接口
2、继承
子类拥有父类非private 的属性和功能
子类具有自己的属性和功能,即可以扩展父类没有的属性和功能
子类可以对父类功能实现重写
继承会破坏包装,父类实现细节会暴露给子类,增加了两个类之间的耦合性,合理的继承才能发挥好的作用。
3、多态
不同的对象可以执行相同的动作,但要通过自己的实现代码来执行
子类以父类的身份出现
子类在工作时以自己的方式进行实现
子类以父类的身份出现时,子类独有的属性和方法不可使用
4、单一职责原则
就一个类而言,应该仅有一个引起它变化的原因。
5、开放-封闭原则
对扩展开放,对修改封闭
6、依赖倒转原则
高层模块不应该依赖于底层模块,两个都应该依赖抽象。
抽象不应该依赖细节,细节应该依赖抽象。
7、里氏代换原则
子类型必须能够替换掉它们的父类型。
只有当子类可以替换掉父类,软件单位的功能不受到影响,父类才能真正被复用,而子类也能够在父类的基础上增加新的行为。
8、迪米特法则
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的方法时,可以通过第三者进行转发这个调用。
在类的结构设计上,每一个类都应当尽量降低成员的访问权限,也就是说,一个类包装好自己的private状态,不需要让别的类知道的字段或行为就不要公开。
迪米特法则的根本思想,就是强调了类之间的松耦合。类之间的耦合越弱,越有利于复用,一个出在弱耦合的类被修改,不会对有关系的类造成波及。
二、工厂模式
1、简单工厂模式
通过一个具体的工厂类,根据传入不同的参数,生成实际对象
2、工厂方法模式
在工厂方法模式中,不再由单一的工厂类生产产品,而是由工厂类的子类实现具体的产品创建。当增加一个产品时,只需增加一个相应的工厂类的子类,实现生产这种产品,从而解决简单工厂生产太多产品导致内部代码臃肿的问题。
3、抽象工厂模式
前提:产品族,如一个工厂生产的洗衣机,冰箱,空调等
产品等级,不同工厂生产的同一中产品,如A 生产的洗衣机,B生产的洗衣机
抽象工厂适用于需要生产产品族的场景。抽象产品类内部提供了多个其他抽象产品,抽象工厂类定义了产品的创建接口,通过具体的工厂子类,就可以生产对应的产品族对象。
三、策略模式
定义了算法家族(拥有同样的方法),分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
场景:商场促销,用打折还是返利。
public class StrategyDemo { public static void main(String[] args) { StrategyContext strategyContext = new StrategyContext(new AddStrategy()); strategyContext.cal(1,2); strategyContext = new StrategyContext(new SubStrategy()); strategyContext.cal(1,2); } } class StrategyContext{//定义策略上下文对象,通过该对象提供通用算法 private IStrategy iStrategy; //通用算法的具体实现 public StrategyContext(IStrategy iStrategy){ this.iStrategy = iStrategy; } public int cal(int a, int b){ return iStrategy.cal(a, b); } } interface IStrategy{ int cal(int a, int b); } //具体+算法 class AddStrategy implements IStrategy{ public int cal(int a, int b){ return a + b; } } //具体-算法 class SubStrategy implements IStrategy{ @Override public int cal(int a, int b) { return a - b; } }
四、装饰模式
动态的给一个对象添加一些额外的职责。
public class DecoratorDemo { public static void main(String[] args) { ISale baseSale = new BaseSale(); SaleDecoratorA saleDecoratorA = new SaleDecoratorA(); SaleDecoratorB saleDecoratorB = new SaleDecoratorB(); //先500-100,再打7折 saleDecoratorA.setSale(baseSale); saleDecoratorB.setSale(saleDecoratorA); System.out.println(saleDecoratorB.acceptCash(500, 1)); //先打7折,再500-100 saleDecoratorB.setSale(baseSale); saleDecoratorA.setSale(saleDecoratorB); System.out.println(saleDecoratorA.acceptCash(500, 1)); System.out.println(saleDecoratorA.acceptCash(1000, 1)); } } interface ISale{ double acceptCash(double price, int num); } class BaseSale implements ISale{ @Override public double acceptCash(double price, int num) { return price * num; } } @Data class SaleDecorator implements ISale{ protected ISale sale; @Override public double acceptCash(double price, int num) { if (sale != null){ return sale.acceptCash(price, num); } return 0; } } class SaleDecoratorA extends SaleDecorator{ private double rebate = 0.7;//打7折 @Override public double acceptCash(double price, int num) { double result = price * num * rebate; return super.acceptCash(result, 1); } } class SaleDecoratorB extends SaleDecorator{ private int moneySum = 500;//满500减100 private int moneySub = 100; @Override public double acceptCash(double price, int num) { double result = price * num; result = result >= moneySum ? result - moneySub : result; return super.acceptCash(result, num); } }
五、代理模式
静态代理和动态代理
六、原型模式
深拷贝和浅拷贝
七、模板方法模式
当需要完成某一细节层次一致的过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,通常考虑用模板方法模式。
模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式通过把不变行为搬移到超类,去除子类中的重复代码来体现优势。
八、外观模式(门面模式)
外观模式:为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
简单理解:使用门面类的方法整合实际调用类的方法,屏蔽调用细节,而由门面类进行实际调用类的复杂方法组合。
什么时候使用外观模式:
1、在设计初期阶段,有意识的将不同的两个层次分离
2、在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观可以提供一个简单的接口,减少依赖
3、在维护一个遗留大系统时,可以开发一个门面类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与门面类交互,门面类与遗留代码交互复杂的工作。
九、建造者模式
又叫生成器模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是在当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时使用的模式。
package com.example.demo; import lombok.AllArgsConstructor; import lombok.Data; import java.util.ArrayList; import java.util.List; public class BuilderDemo { public static void main(String[] args) { ProductABuilder productABuilder = new ProductABuilder(); ProductBBuilder productBBuilder = new ProductBBuilder(); Director director = new Director(productABuilder); director.construct(); Product pA = productABuilder.getResult(); pA.show(); director = new Director(productBBuilder); director.construct(); Product pB = productBBuilder.getResult(); pB.show(); } } interface Builder{ abstract void buildPart1(); abstract void buildPart2(); abstract Product getResult(); } class Product{ List<String> props = new ArrayList<String>(); public void add(String prop){ props.add(prop); } public void show(){ for(String s: props){ System.out.println(s); } } } class ProductABuilder implements Builder{ Product p = new Product(); @Override public void buildPart1() { p.add("PartA1"); } @Override public void buildPart2() { p.add("PartA2"); } @Override public Product getResult() { return p; } } class ProductBBuilder implements Builder{ Product p = new Product(); @Override public void buildPart1() { p.add("PartB1"); } @Override public void buildPart2() { p.add("PartB2"); } @Override public Product getResult() { return p; } } @Data @AllArgsConstructor class Director{ private Builder builder; public void construct(){ builder.buildPart1(); builder.buildPart2(); } }
10、观察者模式
又叫做发布-订阅模式。定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够主动更新自己。
11、状态模式
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
package com.example.demo; import lombok.Data; public class StateDemo { public static void main(String[] args) { Context context = new Context(); context.setState(new StateA()); context.request(); context.request(); context.request(); } } @Data class Context{ private State state; public void request(){ this.state.handle(this); } } interface State{ void handle(Context context); } class StateA implements State{ @Override public void handle(Context context) { System.out.println("当前状态:" + context.getState().getClass().getName()); context.setState(new StateB()); } } class StateB implements State{ @Override public void handle(Context context) { System.out.println("当前状态:" + context.getState().getClass().getName()); context.setState(new StateA()); } }
12、适配器模式
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
13、备忘录模式