<head first 设计模式>学习笔记

[align=center][img]http://images.china-pub.com/ebook35001-40000/36020/shupi.jpg[/img][/align]
这是一本差不多以漫画的形式, 以java语言来讲解设计模式, 很多原来不是很清楚的地方在这本书里面豁然开朗.算是对设计模式的一个复习和加深, 这本书很多讲解设计模式都是采用如何由一般的编码实现完成到设计模式的演变.也可以说是重构的一种最佳实践.而且还让人识别在某种情况下需要实现何种设计模式

[b]设计原则[/b]
找出应用中可能需要变化之处, 把它们独立出来, 并加以封装, 不要和那些不需要变化的代码混在一起
设计模式就是将一些隐含的oo开发经验进行总结归纳的结果
设计是一门艺术, 总是有许多可取舍的地方.但是如果你能采用这些经过深思熟虑, 且经受过时间考验的设计模式, 你就领先别人了.
有一些面向对象原则, 适用于所有的模式. 当你无法找到适当的模式解决问题时, 采用这些原则可以帮助你.
对于一个设计者来说,真正需要关心的是建立弹性的设计,可以维护, 可以应付变化

[b]观察者模式[/b]
如果你了解报纸出版是怎么回事, 你就了解观察者是怎么回事儿了, 只是换了一个名字而已, 出版者改成了"主题(Subject)", 订阅者改成了"观察者(Observer)"而已

[b]工厂模式[/b]
当看到new的时候, 就会想到具体化, 想到跟具体实现绑定, 想到这可能不是一种很好的设计, 可能违背"针对接口编程, 而不是具体实现"
new本身没有错, 只是当遇到需要变化的时候, 就会出现设计不佳的问题

将new实例的部分从代码中抽取出来, 并封装成一个类, 这个类就实现了简单工厂方法, 如果这个工厂创建实例的方式是静态的, 就成了静态工厂方法, 使用静态工厂方法有一个弊端就是没法通过继承来改变创建实例方法的行为

将创建实例的代码封装在一个方法中, 如果这个创建过程的实现可能会有多种, 那么将该方法声明为抽象方法, 然后由子类承担创建的任务, 这种做法就是抽象工厂的做法, 比如这样声明:
abstract Product factoryMethod(String type);

工厂方法模式涉及到两种角色:创建者, 就是那个提供抽象工厂方法的类, 另一个就是产品类, 就是创建的具体东西, 一般是一个接口.
工厂方法的核心就是在抽象类中提供工厂方法的定义, 具体的创建过程到子类中实现.

工厂方法是一种比较好的实现依赖倒置原则的方式.

依赖倒置原则(要依赖抽象, 而不是具体类)和"针对接口编程, 而不是实现"的区别在于, 前者更强调对抽象的依赖

避免违反依赖倒置原则的做法:
1.变量不能持有具体类的引用.如果实用new, 就会持有具体类的引用. 可以采用工厂方法来避开这种做法
2.不要让类派生自具体类, 如果派生自具体类, 就会依赖具体类, 而应该派生自一个抽象(接口和抽象类)
3.不要覆盖基类中已实现的方法. 如果覆盖基类中已实现的方法, 那么呃逆的基类就不是一个真正适合被继承的抽象.基类中实现的方法, 应该由子类共享.

抽象工厂模式实际上可以看着一组工厂方法的合集, 因为他是为了创建一组相关或依赖的对象家族.

[b]单例模式[/b]
单例模式的一般做法:一个私有构造器, 一个静态方法和一个指向实例化对象的静态变量, 但是返回单例有两种处理方式, 一种是贪婪初始化, 就是在静态初始化的时候创建单例, 这样做的好处就是可以保证线程安全, 但是这种方式主要针对初始化不是很耗资源的情况.另一种延迟初始化, 直到在返回单例前先判断是否初始化, 没有则初始化, 有则返回已经初始化对象. 但是这种做法的一个弊端就是在多线程的情况下容易出现并发的问题, 其解决办法有两种, 一种是将静态方法加synchronized关键字, 但是这种做法的执行效率会下降很多.另一种做法就是:
private volatile static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if (uniqueInstance == null){
synchronized(Singleton.class){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
}
}
}


如果单例类采用多个不同的类加载器加载的话, 会出现同事存在多个单例的怪现象. 所以如果程序实用了多个类加载器同时又实用了单例模式, 需要执行制定同一个类加载器来加载单例类

[b]命令模式[/b]
命令模式可以将命令的执行者与命令的请求者解耦.

[b]门面模式[/b]
门面模式中涉及到一个"最少知识原则", 即之和你的密友谈话. 这个原则希望不要让太多的类耦合在一起, 免得修改系统中一部分, 会影响到其他部门分, 如果许多类之间相互依赖, 那么这个系统就会变成一个不稳定的系统, 需要花更多的维护成本.
像这样的代码:
return station.getThermometer().getTemperature();

应该改成:
station.getTemperature();

要避免这种情况的的做法:
对于任何对象而言, 在该对象的方法类, 我们只应该调用属于以下范围的方法:
该对象本身;
呗当作方法的参数传递进来的对象;
此方法所创建或实例化的任何对象;
对象的任何组件
这个原则的一个缺点, 是会造成更多的包装类被提供出来, 对性能会有一定的影响.

[b]模板方法[/b]
定义了一个算法的步骤, 并允许子类为一个或多个步骤提供具体的实现

[b]状态模式[/b]
在处理状态的改变的时候, 我们一般的做法就是给每个状态定义一个常量, 然后在不同的操作的时候, 对当前的状态值进行修改.这样做的一个不好的地方在于, 如果我们增加了一种新的状态的话, 修改起来会非常的麻烦, 这种情况下, 不变的是行为(如果行为也是可变的, 状态模式就不是很合适了), 而变化的是状态值, 所以这里我们就应该应用"将变化的部分加以封装"的原则, 将稳定的行为用接口的方式加以固定, 每一种状态用一个类进行封装. 采用状态模式之后:
1.将每个状态的行为局部化到他自己的类中
2.将容易产生问题的if语句删除, 以方便日后的维护.
3.让每一个状态"对修改关闭", 让糖果机"对扩展开放", 因为可以加入新的状态类.

[b]代理模式[/b]
为另一个对象提供一个替身或占位符以控制对这个对象的访问
代理模式有很多变体, 而这些变体几乎都和"控制访问"的做法有关.比如远程代理控制访问远程对象, 虚拟代理控制访问创建开销比较大的资源.保护代理基于权限控制对资源的访问.
代理模式和装饰模式比较类似, 二者的区别是, 前者是控制对象的访问, 后者是为对象增加行为
代理和适配器的区别, 前者是实现相同的接口, 后者是改变对象适配的接口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值