java学习笔记之 设计模式-套路

–2017年12月14日
所谓设计模式,是大牛门总结的一种解题思路,是一种方法论,俗称套路
另外画UML图对理清设计模式特别有用,而弄明白设计模式对看各种源码特别有用

–20171215 没有那种设计模式是万能的 总会有缺点 特别是随着需求的复杂度提升而带来的不可避免的难度提升,所以我们只能找到最适合的 代码太多了 后续传项目附件吧 这里就只记录总结了

–偶然看到@水谷写的比较详细 类图也上了https://www.cnblogs.com/shuigu/p/6911822.html


  1. 面向对象的设计原则

    为了方便拓展而设计的总则
    说三点比较常见的原则:
    单一职责:功能单一
    开闭原则:对源码的更改关闭,对拓展开放
    优先关联次继承:继承会造成父类的更改时必须更改全部子类,所以优先选用关联关系

  2. 设计模式的分类
    设计模式是在设计原则的基础上,在某些特定场景下而总结的解决方案
    a.创造对象 –>创造型
    b.对象或类之间的组合 –>结构型
    c.对象或类之间的职责分配已经交互 –>行为型

    四人帮GOF N年前定义了23种设计模式,实际常用的也就哪些种 不常用的就不研究了

  3. 创造型模式

3.1.单例模式singletonPattern:只有一个实例

   who:最常见最简单的一种,即只有一个实例
   why:不用反复创建对象/销毁对象,节省这部分时间空间花销
   how:禁止构造实例--private 构造方法()
       提供获取唯一实例的方法-- public Myclass getInstance()
   write:
   where:资源方面的工具类Calendar.getInstance,spring的IOC里的bean实例(算是广义上的单例,new一个对象放在IOC中 然后一直只用这一个对象)

question:单例类通过反射可以创建新的实例吗?–无参构造方法private了

Class<?> clazz = Class.forName("com.pafa.wenching.learn.designPattern.singletonPattern.SingletonLazy");
Constructor<?> declaredConstructor2 = clazz.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
Object newInstance = declaredConstructor.newInstance("xxx");

很遗憾 反射很强大 私有的构造方法也逃不过反射

question:单例类和静态方法

在一些工具类中,静态方法可以替代单例类,
1.从设计思想上说单例类更符合面向对象思想,因为使用的是对象,
2.静态方法过多可能造成方法区溢出

question:拓展成创建固定数量实例的类

在现有单例中,int maxNum,List<MyClass> instances,new的时候条件改变下,getInstance从集合里面取

question:单例类能被继承吗 –>一般不能,Eclipse直接编译不过



3.2.简单工厂-工厂方法-抽象工厂模式(FactoryPattern):创造大量对象,因需求复杂度或者维度而逐渐升级

   who:对象工厂 故名思议 创建大量对象的工厂
   why:为使用者提供创建对象的便利性,省去对象创建的过程
   how:
      1.简单工厂  如果只有简单的固定的产品需要创建,直接用if else判断并创建即可,但拓展新增产品时就需要改工厂源代码了,违反开闭原则
      2.工厂方法  如果产品较多并且为了方便拓展时不违法开闭,就需要由简单工厂升级成工厂方法模式,
      3.抽象工厂  工厂方法模式一个工厂只能产生一个产品,如果一个产品再细分成产品族,那就需要抽象工厂,
   write:
   where:sqlSessionFactory/BeanFactory

ps:每个子类单一职责的生产一种对象 一个多产品类的项目 会多出很多工厂子类 这种浪费和复杂度是由需求的复杂度提示而不可避免的带来的

    public Human getHuman();-- 工厂   人分男女  男女工厂分别生产男女

    -- 抽象工厂  人分男女 男女又分别分黑白黄种人 
   public HumanB getHumanB();//获的黑人  --再由男女工厂实现这三个方法 获取实例对象
    public HumanY getHumanY();//获得黄种人
    public HumanW getHumanW();//获得白种人


3.3.建造者模式(BuliderPattern):针对对象的创建过程比较复杂 类似建房子需要很多组件

   who:创建对象时需要用到比较多的组件,比如需要用到其他类/方法
   why:隐藏建造过程
   how:new StringBulider("x"){super(16),append(x)}
   write:
   where:StringBulider(建造时需要创建arr/append)


3.4.原型模式(PrototypePattern):浅拷贝/深拷贝

   who:即以旧对象为原型创造新的对象
   why:如果一个类对象间的属性多而差异小,则可以用原型对象省去赋值的过程
   how:object的clone方法即浅拷贝,需要重新clone方法才能实现深拷贝
   write:
   where: 

ps:感觉使用范围好小,属性多的对象copy的时候可能相同 但后期维护又觉得可能需要改 并且可能clone这个对象时其值在多线程情况下被不可知的变更了



4.结构型模式–对象或类直接的关系 ABCDFFP

4.1.适配器(AdapterPattern):一个接口变成另外一个接口

   who:通俗的讲就是讲一个接口变成另外一个接口
   why:前期设计时没考虑到的,后期拓展时可以通过适配器去拓展原有的接口功能
   how:适配器和目标类都实现同一接口,然后适配器重写这个接口,就可以搞定了哈
   write:
   where:RunnableAdapter/FutureAdapter

question:代码上看和装饰者以及代理都有点类似呀 –>都拓展原接口的方法 但核心区别在于适配器是为了将一个接口变成另外一个接口,装饰者是为了某个接口提供特定的功能拓展,代理是提供通用的功能拓展

class RunnableAdapter implements Callable<T>{
    //两个属性
    public RunnableAdapter(Runnable runnable,T result){
        //构造方法赋值 this...=..
    }

    public T call(){
        runnable.run();
        return result;
    }


}


4.2 桥接模式(BridgePattern)

   who:两个继承体系间用用高级别的连接起来
   why:聚合/组合原则;开闭原则
   how:abstract Myclass{private IMyClass1 myclass1; private IMyClass myclass2}
       Myclass又有自己的子类    myclass各有自己的体系  但和ImyClass1之间是松耦合的
   write:
   where:这个模式感觉日常经常使用 


4.3 组合模式(ComponentPattern):树形结构专用

   who:针对类的树形结构,而设计的解决方案,设计一个容器类,可以自动处理容器和叶子,而不用用户去区分处理
   why:
   how:
   write:
   where:树形结构的,如文件目录,SAX解析XML


4.4 装饰器模式(DecoratorPattern):拓展中 继承的另外一种形式

   who:继承原接口并持有原接口的引用 并对其拓展
   why:聚合/组合原则
   how:
   write:
   where:IO中的BufferedRead/BufferedWriter是比较典型的
public class BufferedWriter implements Writer{
    private Writer out;

    public void flush() throws IOException{
        synchronized (lock) {
            flushBuffer();
            out.flush();
        }
    }
}


4.5 享元模式:不常用
4.6 外观模式:不常用
4.7 代理模式(ProxyPattern)

   who:对通用功能进行拓展
   why:开闭原则
   how:jdk InvocationHandle接口,动态的生成实现了目标的接口的类的class; cglib则是动态的继承并生成含有代理代码的字节码
   write:
   where:SpringAOP典型应用

ps:静态代理拓展性太差,实用性不强,研究价值不大
question:装饰者和动态代理都是拓展,区别在于装饰者是指定接口,定制版本,拓展定制功能,而动态代理不需要指定接口 是大众版本,对拓展出通用型的功能



5.行为型模式–职责区分/交互 模式较多 不常用的不研究了

5.1 策略模式(StrategyPattern):同一职责下有多种实现方法,策略模式就是解决算法的可替换

   who:定义一系列算法,把它们一个个封装起来,并且使它们可互相替换
   why:算法和客户 解耦
   how:参考桥接模式,但并不关心算法的调用方是否会有子类实现
   write:
   where:这就有很多了呀   比如我们常写代码时有时也是用Object object或者以接口作为属性

question:和桥接模式有点类似,同样是持有接口而不是具体实现类的引用,便于替换,两者的差别主要在于桥接模式的核心思想是两个体系之间的松耦合,而策略模式的重点只停留在自己体系间的解耦



5.2 观察者模式(ObserverPattern):重点为交互,通知其他职责开始工作

   who:
   why:
   how:class MyEvent{
        open(){
            //循环通知所有监听者 
            observer.update()
        }
    }
   write:
   where:各种事件监听就用到了观察者 


5.3 模板方法模式(Template Method Pattern):抽象类定义一个模板,子类对其中某些方法进行实现

   who:
   why:代码复用,减少重复代码
   how:子类需要实现的方法分为抽象方法   钩子方法   钩子方法实际上父类已经实现了 子类重写可以控制父类的行为
   write:
   where:spring中很多应用 如jdbcTemplate


5.4 迭代器模式(IteratiorPattern):不暴露内部表示的情况下 遍历集合

   who:
   why:将遍历的功能单独提取至迭代器接口,符合单一职责
   how:
   write:
   where:毫无疑问的会想到java.util.Iteratior接口 ArrayList有专门的ArrayListIteratior;组合的对象集合


5.5 命令模式(CommandPattern):多个操作整合成一个命令 隐藏命令的内部细节 可回滚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值