在java开发过程中,或者各种语言在编程过程中,对基础知识的累计,这其中就会包含java的设计思想及设计原则及设计模式;我们想对当前的架构以及某些功能逻辑进行优化,及繁简,更加适合当前业务的开发,如何让人一看就能懂得代码,以及各种热门框架 包括spring mybatis 等等热门框架,我们想对其中进行研究,以及或者自己写一个比较好得框架,这一定是离不开得。除了java基础知识,优化, 这就是 研究设计原则和设计模式得意义对于开发,深层次得了解,有着更大的意义,废话不多说 从设计思想开始说起。
面向对象程序设计(Object Oriented Programming,OOP)是一种计算机编程架构。OOP的一条基本原则是计算机程序由单个能够起到子程序作用的单元或对象组合而成。OOP达到了软件工程的三个主要目标:重用性、灵活性和扩展性。OOP=对象+类+继承+多态+消息,其中核心概念是类和对象。
在其中很重要的概念 ,类 接口 抽象类
类是做什么用的
定义功能使用者和功能提供者间的接口
为什么要有接口,隔离开变化 这是他存在的意义。
oop衍生出三大特性 封装 、继承、多态
两种方式,继承 和组合 的方式。
如果你是有一定的开发经验,就会非常容易理解,包括源代码也好 还是 自己写的逻辑也罢,都是这样进行往上进行扩展的, 逃不开这个
继承和 组合的方式。 在实际开发中非常有用。
当oop的这些特性,怎么在开发中使用起来 玩转,充分使用。 就简单使用 oop三大特性是不能满足的。然后衍生出了 设计模式。
在实际开发中,也是 尽量的减少代码的修改 这就是我们最终想达到的效果。
指导我们 如何撸代码 如何写接口 和类 写方法。
理清现实 区分变与不变 搞清楚会如何变 使用者如何隔绝变化 这些都是要我们在现实中需要思考 这都是在开发中遇到的,有些地方根据需求就要变化 功能增强等等。 有些功能是不可能变得。 但是要找到变化得部分 抽象出来,这都是 在平常开发中肯定会遇到得。
设计的体现:如何来定义类、接口、方法
隔离,封装变化的部分,让其他部分不受它的影响。
不同得变化方式,就需要使用不同得设计模式,
设计原则 是面向对象的指导思想,其实有时候在开发过程中你并没有特意去写设计模式,但是重构代码时,一不小心就写除了 设计模式。
这些其实告诉我们 ,代码尽量复用 ,别对以前的代码进行 进行修改呀 单一职责,这都是 上面原则要告诉我们的事。
这其中也涉及相对矛盾的地方,比如里氏替换 和组合复用。都需要根据不同的场合使用的。
应用场景
对于不同的活动的实现。后端代码中如何来灵活应对订单金额
使用switch case的代码。
这虽然没有使用 策略模式,但是我在看到不同的业务场景,在项目上也发现了很多,也是很简单的。场景比较少的情况。就采用这种方式,也没问题的。也是在于不同的应用场景不同的使用方式。
策略模式的实现
利用类来将变化部分 抽象出来。
其实策略模式 就是利用类来将变化部分 抽象出来。 但是把真正使用时,肯定需要结合抽象工厂模式来使用,因为只是简单使用接口去隔离开确实达不到想要的效果,对于类也相对来说会继续增加的。
工厂模式也就是为了将我们我们创建类给抽象出来 不要让我们自己来一个业务需求就创建一个类。
简单工厂模式:所有产品由一个工厂创建
简单工厂模式 工厂中的代码也不要随促销的变化而变化
而在spring中 怎么利用工厂去创建类
通过一个map的方式 存储起来,根据不同的beanname去创建对应的类。
public class PromotionCalculationFactory {
private Map maps;
/*
public PromotionCalculation getPromotionCalculation(String promotion) {
switch() {
// ......
}
}
*/
public PromotionCalculation getPromotionCalculation(String promotion) {
PromotionCalculation prom = maps.get(promotion);
if (prom == null) {
// 从配置的地方加载
prom = getFromDb(promotion);
if (prom != null)
maps.put(promotion, prom);
}
return prom;
}
// spring bean初始化方法
public void init() {
// 第一次将所有的促销策略都加载到Map中
}
// 从数据库加载配置信息,也可以从配置文件加载
private PromotionCalculation getFromDb(String promotion) {
// 从数据库中取到对应的类名
//配置的格式: promotion1=com.study.dn.promotion.calculation.Promotion1
// TODO String className = 从数据库(或其他配置源)中获得;
// 加载类信息
// TODO Class c = Class.forName(className);
// 实例化
// 返回
return null;
}
}
这就是一个简单工厂得实现形式。
通过factorypaoducer去选择创建工厂类代工厂。利用接口去抽象出工厂,然后利用工厂去创建创建不同的类。
不能过度设计的,只有变化需求,扩展时,才使用的。
灵活的将功能进行叠加,这里就需要说到装饰着模式了。
相当于俄罗斯套娃那样。将功能一层层进行叠加。
fileterinputstream 委托给 tuputstream 进行操作 并附加增强功能 在使用时则需要将需要装饰的对象传进去 这就是。组合 替代了 继承的操作。
包含一个被装饰者,基于被装饰者实现的前后增强实现逻辑,对方法结果进行修改,扩展功能。
/**
* 功能增强
*/
public class DecoratorA extends Decorator {
public DecoratorA(Component component) {
super(component);
}
public String methodA() {
return this.component.methodA() + " + A";
}
public int methodB() {
return this.component.methodB() + 10;
}
}
达到对于功能进行增强了
在原来的基础上不断进行增强。
其他的 任何调用,都让代理者进行操作。
代理模式:控制访问者的权限,封装起来,只暴露部分方法。
静态代理:
public interface Girl {
boolean dating(float length);
}
然后 代理类 判断是否可以使用
/**
* 经纪人公司,JDK动态代理实现
*
*/
public class TonyCompany {
public static Object proxy(Object target) {
// 只能基于接口代理
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new MyInvationHandler(target));
}
// 功能增强实现
private static class MyInvationHandler implements InvocationHandler {
private Object target;
public MyInvationHandler(Object target) {
super();
this.target = target;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
doSomethingBefore();
// 调用被代理对象的方法
Object res = method.invoke(target, args);
// 后置增强
doSomethingAfter();
return res;
}
private void doSomethingAfter() {
System.out.println("");
}
private void doSomethingBefore() {
System.out.println("");
}
}
}
持有代理的对象。
/**
* 静态代理的实现
*/
public class Tony implements Girl {
private Girl girl;
public Girl getGirl() {
return girl;
}
public void setGirl(Girl girl) {
this.girl = girl;
}
public boolean dating(float length) {
// 前置增强
doSomethingBefore();
boolean res = this.girl.dating(length);
// 后置增强
doSomethingAfter();
return res;
}
private void doSomethingBefore() {
System.out.println("老板,这个我试过了,很不错,推荐给你!");
}
private void doSomethingAfter() {
System.out.println("老板,你觉得怎样,欢迎下次再约!");
}
}
最后达到代理的效果
静态代理的差点就是 要根据不同代理对象去修改。
扩展能力差
动态代理:动态不同为类的对象创建代理。增强代理。灵活实现:
实现方式
整个动态代理,需要代理的接口 ,new出来被代理的对象。也就是 动态给我们创建一个$proxy,也就是不用我们自己去创建这个类。因此 需要 invocationhandler 进行动态代理。
把需要增强的功能代码在 invocationhandler上实现就行。
基于接口的动态代理。代理对象给我就行。
Girl tony1 = (Girl) TonyCompany.proxy(tc);
th.dating(tony1);
这里就会产生一个代理的实现类
这都是动态代理应该调用到的, 包括权限校验等等。
cglib动态代理
生成字节码。
ASM:一个低层次的字节码操作库
主要作用
使用和实现方式和jdk中动态代理是很像的。
代理的实现类。
会到具体的方法上面去。
最常见的应用就是springmvc中的使用。
如果当我们不需要下个链条是 不用执行下面代码就可以了。
chain.process(request);
应用在 使用者依赖的接口与提供者的接口不匹配时,就加一层适配,而不改两端的代码。
使用转换器来将不符合的代码进行转换。
适配器的模式 将不同的接口连起来,但是针对的是类进行兼容。然后适配
应用场景:
设计原则:迪米特原则,最少知识原则
只需要装饰起来 中介开。他会把所有要做的存储起来,这个在应用中使用的非常多,我们只需要一点就行,其他的,都帮我们做了。
这个模式在我们开发过程中也会遇到很多把,微信公众号,关注就可以收到推送的消息,取消关注,就不会再收到。 以及在什么消息中间件中的思想也是采用 也就是发布订阅。
项目开发中 我之前用到的就是 android 应用启动时,将所有需要启动的类,都做一个启动方法。
应用场景
对于命令不同的实现, 而且不固定 大量时,动态的添加
采用map的方式,去解决 这种 if else的方式,
并且将具体的功能给抽象出来,扩展成不同的格式来处理
这个和策略模式很像,但是不一样。
而策略模式更加简单一点 ,不会来存储这个变化的部分。从而达到实现大量的变化。
根据状态去控制行为。
命令模式的变化部分 就是状态,所以需要把状态 抽象化。成为接口。对应的方法。 这也是整个设计模式需要,通过接口 或者抽象类去实现。
对比 状态模式-命令模式-策略模式
两个以上的模式进行组合,复合模式
会导致类爆炸的, 发生变化的主要是颜色和图形 都会变化。
能抽象 但是组合起来是比较麻烦的。
而桥接模式就是解决这种 情况的。
组合:将抽象组合在一起(桥接)
减少类对象的创建
在实例化时就初始化好类对象。
public class Singleton {
private final static Singleton INSTANCE = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return INSTANCE;
}
}
public class Singleton {
private static Singleton instance;
static {
instance = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
public class Singleton {
private static Singleton singleton;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
缺点:实例化后就不应该再同步了,效率低。
其实根据需要 还是实现采用双重检查
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
public class Singleton {
private Singleton() {}
private static class SingletonInstance {
private static final Singleton INSTANCE =
new Singleton();
}
public static Singleton getInstance() {
return SingletonInstance.INSTANCE;
}
}
优点:避免了线程不安全,延迟加载,效率高。
只要调用getinstance就不会创建 singletoninstance类的。
用枚举的方式
public enum Singleton {
INSTANCE;
public void whateverMethod() {
} }
public abstract class Game {
protected abstract void initialize();
protected abstract void startPlay();
protected abstract void endPlay();
//模板方法
public final void play(){
//初始化游戏
initialize();
//开始游戏
startPlay();
//结束游戏
endPlay();
}
}
优点