文章目录
简介
下图是分类 我这篇文章就按照目的分类写了
模式说明:
• 单例(Singleton)模式:
某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
• 原型(Prototype)模式:
将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
• 工厂方法(Factory Method)模式:
定义一个用于创建产品的接口,由子类决定生产什么产品。
• 抽象工厂(Abstract Factory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
• 建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
• 代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
• 适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
• 桥接(Bridge)模式:将抽象与实现分离,使他们可以独立的变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这2个可变维度的耦合度。
• 装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。
• 外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
• 享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。
• 组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
• 模板方法(Template Method)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
• 策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使他们可以相互替换,且算法的改变不会影响到使用算法的客户。
• 命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
• 职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
• 状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。
• 观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其它多个对象,从而影响其它对象的行为。
• 中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
• 迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
• 访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
• 备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
• 解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
创建型模式
用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF中提供了5种创建型模式
单例模式
确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。
结构
代码
public class Singleton {
private static Singleton instance=null; //静态私有成员变量
//私有构造函数
private Singleton() {
}
//静态公有工厂方法,返回唯一实例
public static Singleton getInstance() {
if(instance==null)
instance=new Singleton();
return instance;
}
}
饿汉式单例类(Eager Singleton)
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() { }
public static EagerSingleton getInstance() {
return instance;
}
}
懒汉式单例类
public class LazySingleton {
private static LazySingleton instance = null;
private LazySingleton() { }
synchronized public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
双重检索 加载
public class LazySingleton {
private volatile static LazySingleton instance = null;
private LazySingleton() { }
public static LazySingleton getInstance() {
//第一重判断
if (instance == null) {
//锁定代码块
synchronized (LazySingleton.class) {
//第二重判断
if (instance == null) {
instance = new LazySingleton(); //创建单例实例
}
}
}
return instance;
}
}
饿汉式单例类与懒汉式单例类的比较
饿汉式单例类:无须考虑多个线程同时访问的问题;调用速度和反应时间优于懒汉式单例;资源利用效率不及懒汉式单例;系统加载时间可能会比较长
懒汉式单例类:实现了延迟加载;必须处理好多个线程同时访问的问题;需通过双重检查锁定等机制进行控制,将导致系统性能受到一定影响
模式优点
提供了对唯一实例的受控访问
可以节约系统资源,提高系统的性能
允许可变数目的实例(多例类)
模式缺点
扩展困难(缺少抽象层)
单例类的职责过重
由于自动垃圾回收机制,可能会导致共享的单例对象的状态丢失
模式适用环境
系统只需要一个实例对象,或者因为资源消耗太大而只允许创建一个对象
客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例
简单工厂模式
简单工厂模式 (Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类
定义
在简单工厂模式中用于创建实例的方法通常是静态(static)方法,因此又被称为静态工厂方法(Static Factory Method)模式
要点:如果需要什么,只需要传入一个正确的参数,就可以获取所需要的对象,而无须知道其创建细节
结构
简单工厂模式包含以下3个角色:
Factory(工厂角色)
Product(抽象产品角色)
ConcreteProduct(具体产品角色)
代码
抽象产品类代码
public abstract class Product {
//所有产品类的公共业务方法
public void methodSame() {
//公共方法的实现
}
//声明抽象业务方法
public abstract void methodDiff();
}
具体产品类
public class ConcreteProduct extends Product{
//实现业务方法
public void methodDiff() {
//业务方法的实现
}
}
具体工厂方法
public class Factory {
//静态工厂方法
public static Product getProduct(String arg) {
Product product = null;
if (arg.equalsIgnoreCase("A")) {
product = new ConcreteProductA();
//初始化设置product
}
else if (arg.equalsIgnoreCase("B")) {
product = new ConcreteProductB();
//初始化设置product
}
return product;
}
}
客户端使用 代码
public class Client {
public static void main(String args[]) {
Product product;
product = Factory.getProduct("A"); //通过工厂类创建产品对象
product.methodSame();
product.methodDiff();
}
}
简单工厂的应用实例
某软件公司要基于Java语言开发一套图表库,该图表库可以为应用系统提供多种不同外观的图表,例如柱状图(HistogramChart)、饼状图(PieChart)、折线图(LineChart)等。该软件公司图表库设计人员希望为应用系统开发人员提供一套灵活易用的图表库,通过设置不同的参数即可得到不同类型的图表,而且可以较为方便地对图表库进行扩展,以便能够在将来增加一些新类型的图表。
现使用简单工厂模式来设计该图表库。
实例类图
实例代码
(1) Chart:抽象图表接口,充当抽象产品类
(2) HistogramChart:柱状图类,充当具体产品类
(3) PieChart:饼状图类,充当具体产品类
(4) LineChart:折线图类,充当具体产品类
(5) ChartFactory:图表工厂类,充当工厂类
(6) Client:客户端测试类
代码
抽象图表接口,充当抽象产品类
public interface Chart {
public void display();
}
柱状图类,充当具体产品类
public class HistogramChart implements Chart {
public HistogramChart() {
System.out.println("创建柱状图!");
}
public void display() {
System.out.println("显示柱状图!");
}
}
折线图类,充当具体产品类
public class LineChart implements Chart {
public LineChart() {
System.out.println("创建折线图!");
}
public void display() {
System.out.println("显示折线图!");
}
}
饼状图类,充当具体产品类
public class PieChart implements Chart {
public PieChart() {
System.out.println("创建饼状图!");
}
public void display() {
System.out.println("显示饼状图!");
}
}
图表工厂类,充当工厂类
public class ChartFactory {
//静态工厂方法
public static Chart getChart(String type) {
Chart chart = null;
if (type.equalsIgnoreCase("histogram")) {
chart = new HistogramChart();
System.out.println("初始化设置柱状图!");
}
else if (type.equalsIgnoreCase("pie")) {
chart = new PieChart();
System.out.println("初始化设置饼状图!");
}
else if (type.equalsIgnoreCase("line")) {
chart = new LineChart();
System.out.println("初始化设置折线图!");
}
return chart;
}
}
客户端类
public class Client {
public static void main(String args[]) {
Chart chart;
//通过静态工厂方法创建产品
chart = ChartFactory.getChart("histogram");
chart.display();
}
}
结果
模式优点
实现了对象创建和使用的分离
客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可
可以通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
模式缺点
工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响
增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度
系统扩展困难,一旦添加新产品不得不修改工厂逻辑
由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展
模式适用环境
工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂
客户端只知道传入工厂类的参数,对于如何创建对象并不关心
工厂方法模式
工厂模式与简单工厂模式的区别
工厂方法模式:
不再提供一个按钮工厂类来统一负责所有产品的创建,而是将具体按钮的创建过程交给专门的工厂子类去完成
如果出现新的按钮类型,只需要为这种新类型的按钮定义一个具体的工厂类就可以创建该新按钮的实例
定义
简称为工厂模式(Factory Pattern)
又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)
工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象
目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类
结构
工厂方法模式包含以下4个角色:
Product(抽象产品)
ConcreteProduct(具体产品)
Factory(抽象工厂)
ConcreteFactory(具体工厂)
代码
抽象工厂类代码
public interface Factory {
public Product factoryMethod();
}
具体工厂类代码
public class ConcreteFactory implements Factory {
public Product factoryMethod() {
return new ConcreteProduct();
}
}
客户端代码片段
Factory factory;
factory = new ConcreteFactory(); //可通过配置文件和反射机制实现
Product product;
product = factory.factoryMethod();
工厂方法模式的应用实例
某系统运行日志记录器(Logger)可以通过多种途径保存系统的运行日志,例如通过文件记录或数据库记录,用户可以通过修改配置文件灵活地更换日志记录方式。在设计各类日志记录器时,开发人员发现需要对日志记录器进行一些初始化工作,初始化参数的设置过程较为复杂,而且某些参数的设置有严格的先后次序,否则可能会发生记录失败。
为了更好地封装记录器的初始化过程并保证多种记录器切换的灵活性,现使用工厂方法模式设计该系统。
实例类图
实例代码
(1) Logger:日志记录器接口,充当抽象产品角色
(2) DatabaseLogger:数据库日志记录器,充当具体产品角色
(3) FileLogger:文件日志记录器,充当具体产品角色
(4) LoggerFactory:日志记录器工厂接口,充当抽象工厂角色
(5) DatabaseLoggerFactory:数据库日志记录器工厂类,充当具体工厂角色
(6) FileLoggerFactory:文件日志记录器工厂类,充当具体工厂角色
(7) Client:客户端测试类
代码
日志记录器接口:抽象产品
public interface ILogger
{
void WriteLog();
}
文件日志记录器:具体产品
public class FileLogger : ILogger{
public void WriteLog()
{
Console.WriteLine("文件日志记录!");
}
}
数据库日志记录器:具体产品
public class DatabaseLogger : ILogger{
public void WriteLog()
{
Console.WriteLine("数据库日志记录!");
}
日志记录器工厂接口:抽象工厂
public interface ILoggerFactory
{
ILogger CreateLogger();
}
文件日志记录器工厂类:具体工厂
public class FileLoggerFactory : ILoggerFactory
{
public ILogger CreateLogger()
{
//创建文件日志记录器对象
var logger = new FileLogger();
//创建文件,省略代码
return logger;
}
}
数据库日志记录器工厂类:具体工厂
public class DatabaseLoggerFactory : ILoggerFactory
{
public ILogger CreateLogger()
{
//连接数据库,代码省略
//创建数据库日志记录器对象
var logger = new DatabaseLogger();
//初始化数据库日志记录器,代码省略
return logger;
}
}
客户端测试代码
```java
class Program
{
static void Main(string[] args)
{
var factory = new FileLoggerFactory();//可引入配置文件实现
var logger = factory.CreateLogger();
logger.WriteLog();
}
}
模式优点
工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节
能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部
在系统中加入新产品时,完全符合开闭原则
模式缺点
系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销
增加了系统的抽象性和理解难度
模式适用环境
客户端不知道它所需要的对象的类(客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体产品对象由具体工厂类创建)
抽象工厂类通过其子类来指定创建哪个对象
抽象工厂模式
定义
又称为工具(Kit)模式
抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品
当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、更有效率
结构
抽象工厂模式的结构
抽象工厂模式包含以下4个角色:
AbstractFactory(抽象工厂)
ConcreteFactory(具体工厂)
AbstractProduct(抽象产品)
ConcreteProduct(具体产品)
代码
典型的抽象工厂类代码:
public interface AbstractFactory {
public AbstractProductA createProductA(); //工厂方法一
public AbstractProductB createProductB(); //工厂方法二
……
}
典型的具体工厂类代码:
public class ConcreteFactory1 implements AbstractFactory {
//工厂方法一
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
//工厂方法二
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
抽象工厂模式的应用实例
实例代码
(1) Button:按钮接口,充当抽象产品
(2) SpringButton:Spring按钮类,充当具体产品
(3) SummerButton:Summer按钮类,充当具体产品
(4) TextField:文本框接口,充当抽象产品
(5) SpringTextField:Spring文本框类,充当具体产品
(6) SummerTextField:Summer文本框类,充当具体产品
(7) ComboBox:组合框接口,充当抽象产品
(8) SpringComboBox:Spring组合框类,充当具体产品
(9) SummerComboBox:Summer组合框类,充当具体产品
(10) SkinFactory:界面皮肤工厂接口,充当抽象工厂
(11) SpringSkinFactory:Spring皮肤工厂,充当具体工厂
(12) SummerSkinFactory:Summer皮肤工厂,充当具体工厂
(13) Client:客户端测试类
代码
模式优点
隔离了具体类的生成,使得客户端并不需要知道什么被创建
当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
增加新的产品族很方便,无须修改已有系统,符合开闭原则
模式缺点
增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则
模式适用环境
一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节
系统中有多于一个的产品族,但每次只使用其中某一产品族
属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来
产品等级结构稳定,在设计完成之后不会向系统中增加新的产品等级结构或者删除已有的产品等级结构
生成器模式
定义
建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
将客户端与包含多个部件的复杂对象的创建过程分离,客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可
如何逐步创建一个复杂的对象,不同的建造者定义了不同的创建过程
结构
建造者模式包含以下4个角色:
Builder(抽象建造者)
ConcreteBuilder(具体建造者)
Product(产品)
Director(指挥者)
代码
典型的复杂对象类代码:
public class Product {
private String partA; //定义部件,部件可以是任意类型,包括值类型和引用类型
private String partB;
private String partC;
//partA的Getter方法和Setter方法省略
//partB的Getter方法和Setter方法省略
//partC的Getter方法和Setter方法省略
}
典型的抽象建造者类代码:
public abstract class Builder {
//创建产品对象
protected Product product=new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
//返回产品对象
public Product getResult() {
return product;
}
}
典型的具体建造者类代码:
public class ConcreteBuilder1 extends Builder{
public void buildPartA() {
product.setPartA("A1");
}
public void buildPartB() {
product.setPartB("B1");
}
public void buildPartC() {
product.setPartC("C1");
}
}
典型的指挥者类代码:
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder=builder;
}
public void setBuilder(Builder builder) {
this.builder=builer;
}
//产品构建与组装方法
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
客户类代码片段:
……
Builder builder = new ConcreteBuilder1(); //可通过配置文件实现
Director director = new Director(builder);
Product product = director.construct();
……
应用实例
某游戏软件公司决定开发一款基于角色扮演的多人在线网络游戏,玩家可以在游戏中扮演虚拟世界中的一个特定角色,角色根据不同的游戏情节和统计数据(例如力量、魔法、技能等)具有不同的能力,角色也会随着不断升级而拥有更加强大的能力。
作为该游戏的一个重要组成部分,需要对游戏角色进行设计,而且随着该游戏的升级将不断增加新的角色。通过分析发现,游戏角色是一个复杂对象,它包含性别、面容等多个组成部分,不同类型的游戏角色,其性别、面容、服装、发型等外部特性都有所差异,例如“天使”拥有美丽的面容和披肩的长发,并身穿一袭白裙;而“恶魔”极其丑陋,留着光头并穿一件刺眼的黑衣。
无论是何种造型的游戏角色,它的创建步骤都大同小异,都需要逐步创建其组成部分,再将各组成部分装配成一个完整的游戏角色。现使用建造者模式来实现游戏角色的创建。
实例代码
(1) Actor:游戏角色类,充当复杂产品对象
(2) ActorBuilder:游戏角色建造者,充当抽象建造者
(3) HeroBuilder:英雄角色建造者,充当具体建造者
(4) AngelBuilder:天使角色建造者,充当具体建造者
(5) DevilBuilder:恶魔角色建造者,充当具体建造者
(6) ActorController:角色控制器,充当指挥者
(7) Client:客户端测试类
代码
模式优点
客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象
每一个具体建造者都相对独立,与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,扩展方便,符合开闭原则
可以更加精细地控制产品的创建过程
模式缺点
建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,不适合使用建造者模式,因此其使用范围受到一定的限制
如果产品的内部变化复杂,可能会需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加了系统的理解难度和运行成本
模式适用环境
需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员变量
需要生成的产品对象的属性相互依赖,需要指定其生成顺序
对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中
隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品
原型模式
定义
原型模式:使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
工作原理:将一个原型对象传给要发动创建的对象(即客户端对象),这个要发动创建的对象通过请求原型对象复制自己来实现创建过程
创建新对象(也称为克隆对象)的工厂就是原型类自身,工厂方法由负责复制原型对象的克隆方法来实现
通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,每一个克隆对象都是独立的
通过不同的方式对克隆对象进行修改以后,可以得到一系列相似但不完全相同的对象
结构
原型模式包含以下3个角色:
Prototype(抽象原型类)
ConcretePrototype(具体原型类)
Client(客户类)
浅克隆与深克隆
浅克隆(Shallow Clone):当原型对象被复制时,只复制它本身和其中包含的值类型的成员变量,而引用类型的成员变量并没有复制
深克隆(Deep Clone):除了对象本身被复制外,对象所包含的所有成员变量也将被复制
代码
public interface Prototype {
public Prototype clone();
}
public class ConcretePrototype implements Prototype {
private String attr;
public void setAttr(String attr) {
this.attr = attr;
}
public String getAttr() {
return this.attr;
}
//克隆方法
public Prototype clone() {
Prototype prototype = new ConcretePrototype(); //创建新对象
prototype.setAttr(this.attr);
return prototype;
}
}
客户端片段
……
ConcretePrototype prototype = new ConcretePrototype();
prototype.setAttr("Sunny");
ConcretePrototype copy = (ConcretePrototype)prototype.clone();
……
结构型模式
用于描述如何将类或对象按某种布局组成更大的结构,GoF中提供了7种结构型模式。
行为型模式
用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF中提供了11种行为型模式。