设计模式入门
1:设计模式是人们在面对同类型软件工程设计问题所总结出的一些有用经验。模式不是代码,而是某类问题的通用设计解决方案。
2:怎么来的,前人总结的
3:设计模式的邮件和用途
4:学习设计模式的方式:在你的设计和以往的工程里寻找何处可以使用它们
5:学习设计模式的本质目的是使软件工程在维护性、拓展性、变化性、复杂度方面称0(N)
6:OO原则,设计模式是具体方法、工具
策略模式:
定义:分别封装行为为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封住接口,基于接口编程各种功能。该模式让行为算法的变化独立于算法的使用者。
ps自我理解:
1:从原始的OO角度设计,抽象出对象的共性,提取至基类
public abstract class Duck {
public void Quack() {
System.out.println("~~gaga~~");
}
public abstract void display();
public void swim() {
System.out.println("~~im swim~~");
}
}
2:相应的各个实现类只需要继承基类就可以使用到基类里面有的方法和重写自己想要的方法
public class GreenHeadDuck extends Duck {
@Override
public void display() {
System.out.println("**GreenHead**");
}
}
3:后来来了新需求
应对新的需求,看看这个设计的可扩展性
添加会飞的鸭子
4:OO思维里的继承方式解决方案是:
public abstract class Duck {
...;
public void Fly() {
System.out.println("~~im fly~~");
}
};
问题来了,这个Fly让所有子类都会飞了,这是不科学的。
继承的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。影响会有溢出效应
5:为了正确性那么你是不是需要去重写所有的实现,这次是所有的鸭子都会飞,下次再来个所有的鸭子都会上树了你咋办?
超类挖的一个坑,每个子类都要来填,增加工作量,复杂度O(N^2)。不是好的设计方式
6:用策略模式来新需求解决
//行为接口
public interface FlyBehavior {
void fly();
}
//基类
public abstract class Duck { //基类
FlyBehavior mFlyBehavior; //行为接口对象 也就是容易变化的地方
QuackBehavior mQuackBehavior; //行为接口对象
public Duck() { }
public void Fly() {
mFlyBehavior.fly(); //行为接口对象的方法 不做具体实现
}
public void Quack() {
mQuackBehavior.quack();
}
public abstract void display(); //共同的地方也就不需要再做什么手脚了 没啥意义
public void SetQuackBehavoir(QuackBehavior qb) {
mQuackBehavior = qb;
}
public void SetFlyBehavoir(FlyBehavior fb) {
mFlyBehavior = fb;
}
public void swim() {
System.out.println("~~im swim~~");
}
}
//行为接口实现
public class BadFlyBehavior implements FlyBehavior
{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("--BadFly--");
}
}
//基类的具体实现类
public class GreenHeadDuck extends Duck {
public GreenHeadDuck() {
mFlyBehavior = new GoodFlyBehavior();
mQuackBehavior = new GaGaQuackBehavior();
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("**GreenHead**");
}
}
策略模式总结:
1:分析项目中变化和不变化的部分。
2:多用组合少用继承,用行为类组合,也不是行为的继承。更有弹性。
装饰者模式:
装饰者模式原理:
1:装饰者模式就像打包一个快递
1)主体:陶瓷、衣服
2)包装:报纸、套末班、纸板
2:Component:主体(超类)
3:ConcreteComponent(具体实现类)和Decortor(实现类的装饰)
4:装饰者模式:
动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性。
单例模式:
经典单例模式原理:
单例模式的意义:
有些对象我们只需要一个:线程池、缓存、硬件设备等,如果多个实例会造成冲突、结果的不一致性等问题。
是否可以用静态变量方式来实现?
或者协商一个全局变量?
单例模式的概念:
确保一个类最多只有一个实例,并提供一个全局访问点。
单例模式类图:
-----------------------
| Singleton |
-----------------------
|static uniqueInstance| //静态变量
|//其他 |
-----------------------
|private Singletom() | //构造函数私有 封闭类在外部new的方式
|static getInstance | //在类的内部使用静态函数构造一个对象
|//其他 |
-----------------------
经典单例模式代码示例:
单例类java代码:
public class Singleton{
private static Singleton uniqueInstance = null; //用于存放自己的实例
private Singleton(){}; //构造函数私有
public static Singletom getInstance(){
if(null == uniqueInstance){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
经典代理模式代码优化:
多线程问题:会出现两个或多个线程获取到两个或多个不同的对象。
优化方式1:创建方法枷锁
public class Singleton{
private static Singleton uniqueInstance = null; //用于存放自己的实例
private Singleton(){}; //构造函数私有
public static synchronized Singletom getInstance(){ //最粗暴的方式 synchronized会多次
if(null == uniqueInstance){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
优化方式2:‘急切’创建实例
public class Singleton{
private static Singleton uniqueInstance = new Singleton(); //用于存放自己的实例 程序启动时就创建好对象
private Singleton(){}; //构造函数私有
public static Singletom getInstance(){
if(null == uniqueInstance){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
优化方式3:双重检查加锁
public class Singleton{
private static volatile Singleton uniqueInstance = null; //用于存放自己的实例
private Singleton(){}; //构造函数私有
public static Singletom getInstance(){
if(null == uniqueInstance){
synchronized (Singleton.class){ //这样也就是再上面内个方法的基础上 优化了加锁的次数 只会有一次 synchronized
if(null == uniqueInstance){
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}
工厂模式:
简单工厂模式的设计方案:
定义一个实例化对象的类,由这个类封装创建对象的行为。
工厂方法模式的设计方案:
将对象的实例化功能抽象成抽象方法,在不同实例里面实现具体功能,
也就是定义一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象实例化推迟到子类。
抽象工厂模式定义:
定义一个接口用于创建相关有依赖关系的对象族,而无需指明具体类。
工厂模式关键点:
1:工厂模式的意义
将对象实例化动作提取,和项目的主动和依赖进行解耦
2:三种工厂模式
3:依赖抽象原则
变量不要持有具体类的引用,不可以强依赖
不要让类继承自具体类,要继承自抽象类或接口
不要覆盖基类中已经实现的方法
适配器模式:
原理:将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容。
目标 <--- 适配器 <--- 被适配者
从用户角度看不到被适配者,是解耦的
用户调用适配器转换出来的目标接口方法
适配器再调用被适配者的相关接口方法
对象适配器与类适配器:
类适配器:通过多重继承目标接口和被适配者类方式来实现适配
目标<--|
|适配器
被适配者<--|
多重继承,其中继承的目标接口部门达到适配目的,而继承被适配者类的部分达到通过调用适配者类里面的方法实现目标接口的功能
对象适配器与类适配器的差异:
对象适配器与类适配器使用了不同的方法实现适配,对象适配器使用组合,类适配器使用继承