Java 6大设计原则28大设计模式
6大设计原则:
1. 单一职责原则
2. 里氏替换原则
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. 依赖倒置原则
- 模块间的依赖通过抽象发生(接口或抽象类)
- 接口或抽象类不依赖于实现类
- 实现类依赖接口或抽象类
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. 迪米特法则
6. 开闭原则
28大设计模式
1. 单例模式
最简单常用的模式,不展开了
public Sun {private static final Sun sun = new Sun();public static Sun getInstance() {return sun;}public void light() {System.out.println("太阳发光");}
}
2. 工厂方法模式
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.(为创建一组相关或相互依赖的对象提供一个接口,而且无须指定它们 的具体类。)
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. 模板方法模式
对于业务模型的业务动作模板化;基本方法在子类中实现,模板方法在父类中调度
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)也叫做生成器模式
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. 代理模式
- 高扩展性,不侵入实现层的源码
- 职能清晰
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. 原型模式
- 对于构造函数消耗的性能非常多且实例化的内容是一致的对象能够大幅提高性能
- 双刃剑:逃避构造函数约束(成也萧何,败也萧何,千万注意此点对业务的影响)
缺点:
- 仅深拷贝本对象(属性如果是对象则为浅拷贝)
- 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. 中介者模式
9. 命令模式
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. 责任链模式
11. 装饰模式
- 装饰类和被装饰类可以独立发展,而不会相互耦合。
- 装饰模式是继承关系的一个替代方案
- 动态扩展类的功能
缺点:
- 不要套太多,套娃太深,复杂度太高,排查和理解耗时
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. 策略模式
- 策略自由切换,方便横向扩展
- 避免多重条件判断
缺点:
- 策略类数量多时,需要有诸葛亮一样的人来运筹帷幄,复用性也低
- 所有策略都得对外暴露
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. 适配器模式
- 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定 他们就成
- 降低了类的存在感,简化使用
- 提供类的复用和灵活性
缺点:
- 个人人为也不算缺点吧,项目初期不用考虑这个模式,大多在维护阶段去使用,去适配未知的场景(就像在中国是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. 迭代器模式
public interface Iterator {//遍历到下一个元素 public Object next(); //是否已经遍历到尾部 public boolean hasNext(); //删除当前指向的元素 public boolean remove();
}
Java本身已经提供了很强大的基础API,所以我们基本不需要自己再去写这些
15. 组合模式
16. 观察者模式
/*** 被观察者*/
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. 备忘录模式
备忘录就像我们处理数据库事务一样,可以对操作进行回滚
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. 访问者模式
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大设计模式相关推荐
- 设计模式01-七大设计原则
设计模式01-七大设计原则 文章目录 设计模式01-七大设计原则 开闭原则-Open Close 依赖倒置原则-Dependence Inversion 单一职责原则-Simple ResponsiB ...
- Java设计模式GOF之6大设计原则
Java设计模式GOF之6大设计原则原则 1.开闭原则(Open Close Principle) 一个软件实体如类.模块和函数应该对扩展开放,对修改关闭. 开闭原则是面向对象的可复用设计的第一块基石 ...
- Java架构师必须知道的 6 大设计原则
转载自 Java架构师必须知道的 6 大设计原则 在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义.本文主要将总结这些常见 ...
- 设计模式 — 6大设计原则(依赖倒置和接口隔离原则)
设计模式 依赖倒置原则 示例 一 示例 二 依赖的三种写法 总结 接口隔离原则 实例 一 总结 依赖倒置原则 依赖倒置原则(Dependence Inversion Principle,DIP)这个名 ...
- 设计模式概述—6大设计原则
第一部分:6大设计原则 六大设计原则: 1)Single Responsibility Principle:单一职责原则 2)Open Closed Principle:开闭原则 3)Liskov S ...
- C++ 设计模式(8大设计原则、23种设计模式)李建忠
简 述: 设计模式,久闻大名.此记录学习 "C++ 设计模式 李建忠" 的札记,核心共 8大设计原则.23中设计模式.后发现 GitHub 也有类似笔记 Ref1 .Ref2 相关 ...
- 设计模式之禅《一》 大旗不挥,谁敢冲锋 ——6大设计原则
设计模式之禅<一>大旗不挥,谁敢冲锋 --6大设计原则 <一> 六大原则 一:单一职责原则 1.单一职责原则最难划分的就是职责 2.有两个可以变化的原因放到了一个接口中,这就为 ...
- 架构设计模式—6大设计原则
架构设计原则 6大设计原则 Single Responsibility Principle : 单一职责原则 Liskov Substitution Principle : 里氏替换原则 Depend ...
- 面向对象设计原则_聊聊面向对象的6大设计原则
程序员都知道编程有 3 大类:面向过程.面向对象.面向函数.面向对象是被讨论的最多的,个人认为,这是因为 Java 之类的编程语言有强大的用户基础,本质还是因为比较符合人的直觉. 说到面向对象,大家可 ...
最新文章
- 解决mac上mariadb不能远程访问的问题
- 用python画烟花-python实现烟花小程序
- android 水平方向瀑布流,Android RecyclerView(瀑布流)水平/垂直方向分割线
- 物化视图 sql server 1
- 特斯拉全球超级充电站已超过25000座 国内超过870座
- 受疫情影响 MWC 2020正式取消
- 51单片机 | 基于I2C总线的秒表模拟应用
- aws lam nodejs mysql_NodeJs IF Statement in AWS Lambda using MySQL database
- Oracle(7)——Oracle修改国家字符集
- 直播app服务器部署,直播视频服务器的选择!
- Redis 6 入门到入坟 详细教程 @学习笔记
- win11更新后任务栏空白怎么办? win11更新后任务栏空白卡死的解决方法
- 解决百度云下载缓慢问题
- golang cpuprofile分析
- 玩转Qml(18)-用户向导
- 利用 css 和 html 实现简单的双心
- 【JavaWeb】JSP(172-190)
- 在阿里这六年,我学到的所有东西都在这了
- Excel如何制作工资表
- Python实现的免费pdf阅读器
热门文章
- 比北漂更苦的,是我们“双色青年”
- 三方直播SDK对比(腾讯云,阿里云,网易云信,七牛云,金山云,声网,即构科技)
- JSP运行原理及运行过程
- 【English】一月英语
- 缩印技巧你知多少?缩印怎么设置?
- 一种输电线路视频图像在线监测装置
- php ci框架开发手册下载,php敏捷开发codeigniter框架-CodeIgniter教程(中文手册)pdf格式免费完整版-东坡下载...
- 使用ASP.NET Core进行跨平台Web文档扫描
- html控制智能家居,一种基于数据库中间件和HTML5的智能家居控制软件系统
- 2016第19本:至关重要的关系