学习设计模式笔记

 总体:对于设计模式其实就是加入了一个中间层

 

简单工厂:对具体实现类较为固定的业务可以使用该模式

缺点:不支持开闭原则,新增加一个实现类需要修改工厂类,也可以采用配置文件方式灵活配置

例子:采用配置文件配置子类

接口类:Api

package api;

public interface Api {
    public void say();
}

 

实现类:ImplA

package api.impl;

import api.Api;

public class ImplA implements Api {
    public void say() {
        System.out.println("I am implA");
    }
}

实现类:ImplB

package api.impl;

import api.Api;

public class ImplB implements Api {
    public void say() {
        System.out.println("I am implB");
    }
}

 

简单工厂类:SimpleFactory

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import api.Api;


public class SimpleFactory {
    public static Api createApi() {
        //读取配置文件
        Properties p = new Properties();
        //读取配置文件流
        InputStream in = null;
        try {
            in = SimpleFactory.class.getResourceAsStream("SimpleFactory.properties");
            //加载流文件到Properties类
            p.load(in);
        } catch (IOException e) {
            System.out.println("配置文件读取出错!!");
            e.printStackTrace();
        } finally{
            if(null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
       
        //反射机制取得对象
        Api api = null;
        try {
            api = (Api)Class.forName(p.getProperty("ImplClass")).newInstance();
        } catch (InstantiationException e) {
            System.out.println("初始化对象出错!!");
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            System.out.println("非法的访问!!");
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            System.out.println("类未找到!!");
            e.printStackTrace();
        }
        return api;
    }
}

客户端类:Client

 import api.Api;

public class Client {
    public static void main(String[] args) {
        Api api = SimpleFactory.createApi();
        api.say();
    }
}

 

配置文件:SimpleFactory.properties,需要放到SimpleFactory用一个目录下即可

ImplClass=api.impl.ImplA

 

本质:选择实现

 

与其他相关模式关系:

简单工厂和抽象工厂

抽象工厂模式是用来选择产品族,抽象类中可以有多个用于选择并创建对象的方法,但是这些方法所创建的对象之间通常是有关系的,这些别创建的对象通常是构成一个产品族所需要的部件对象

 

简单工厂和工厂方法

工厂方法的本质也是用来选择实现的,跟简单工厂的区别在于工厂方法是吧选择具体实现的功能延迟到子类中实现。如果把工厂方法中选择的实现放到父类直接实现,就等同于简单工厂。

 

 

工厂方法:实现了OCP原则

缺点:只能够创建单一产品系列

 

 

 

 

抽象工厂和工厂方法区别:

工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。   
一个抽象工厂类,可以派生出多个具体工厂类。   
每个具体工厂类可以创建多个具体产品类的实例。   
    
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。   
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

 

 

 

 

 

门面模式:

定义:定义子系统的多个模块对外的高层接口,通常需要调用内部多个模块,从而把客户的请求代理给适当的子系统对象

Facade代码上将客户端调用各个模块中的方法变成了调用门面类的方法,在该方法中是真正的调用模块方法,这样做可以将隐藏某个功能的具体细节,当该功能需要修改时将不会影响客户端,只需要修改门面类即可,但也可以不使用门面类,可以直接调用某个类的方法,类似一站式服务,同时也类似于医院的接待处,通过接待员和医院内部人员的配合完成患者的需求。

 

使用场景:

希望为一个复杂的子系统提供一个简单接口的时候,可以考虑使用外观模式。使用外观对象来实现大部分客户需要的功能,从而简化客户的使用

 

与其他模式区别:

中介者模式主要用来封装多个对象之间相互的交互

 

适配器模式

定义:将几个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

角色:Target为新接口,Adaptee为老的实现,Adapter为适配器类(实现了Target接口,在具体方法中调用了Adaptee的实现)

功能:

适配器模式的主要功能是进行转换匹配,目的是服用已有的功能,而不是来实现新接口。也就是说,客户端需要的功能应该是已经实现好了的,不需要适配器模式来实现,适配器模式主要负责吧不兼容的接口转换成客户期望的样子

 

对象组合:

根据前面的实现,你会发现,适配器的实现方式其实就是靠对象组合的方式,通过给适配器对象组合配饰配的对象,然后当客户端调用Target的时候,适配器会把相应功能委托给被失陪的对象去完成。

 

适配器模式的实现

 智能适配器:一般新加入功能的实现会用到很多Adaptee的功能,这种情况就需要在适配器的实现里面加入新功能的实现,这种适配器被称为智能适配器

适配多个Adaptee:可以适配多个Adaptee,这就是说实现某个新的Target接口的时候需要多个模块的功能。

 

缺省适配:为了一个接口提供缺省实现

 

双向适配器

即把Adaptee适配成为Target,有把Target适配为Adaptee

 

分类

对象适配器和类适配器

对象适配器:依赖于对象组合

类适配器:采用多重继承对一个接口与另外一个接口进行匹配,可以采用实现Target接口和继承Adaptee的方式类似于类适配器,其实与双向适配器,Target和Adaptee的方法都有,一个实现,一个继承。

 

优缺点:

优点:更好的复用性、可扩展性

缺点:过多的使用会导致系统非常凌乱,不容易整体进行把握

 

 单例模式

定义:保证一个类只有一个实例,并提供一个全局访问它的全局访问点

分类:懒汉式和饿汉式

懒汉式:需要第一次使用时才new对象,并且getInstance方法需要时同步的synchronized,并发有问题

饿汉式:在类初始化时就将new出对象,不需要加同步锁synchronized,并发不存在问题

 

 “双重检查加锁“无效的原因:内存模型导致,无序写入,在懒汉式中当对象还没有构造成功的间隙会有其他线程进入代码块判断instance为非null,直接返回,而这时对象还未创建成功,会导致问题

 

工厂方法

定义:让父类在不知道具体实现的情况下,完成自身的功能调用;而具体的实现延迟到子类来实现,其中用来创建对象的方法就是工厂方法。

小结:在工厂方法模式里面,客户端要么使用工厂类对象,要么使用工厂创建出的对象,一般客户端不直接使用工厂方法,当然也可以直接使用,但是不建议。

 

抽象工厂

 定义:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类

可以有多个抽象接口类,而工厂方法只有一个

实质:选择产品族的实现,定义在抽象工厂离得方法是有联系的,他们都是产品的某一部分或者是相互依赖的

 

生成器模式

 

 

 

;