目录
设计模式的分类
根据目的(模式是用来做什么的)可分为创建型(Creational),结构型(Structural)和行为型(Behavioral)三类:
- 创建型模式主要用于创建对象
- 结构型模式主要用于处理类或对象的组合
- 行为型模式主要用于描述类或对象如何交互和怎样分配职责
创建型模式
- 抽象工厂模式(Abstract Factory)
- 建造者模式(Builder)
- 工厂方法模式(Factory Method)
- 原型模式(Prototype)
- 单例模式(Singleton)
结构型模式
- 适配器模式(Adapter)
- 桥接模式(Bridge)
- 组合模式(Composite)
- 装饰模式(Decorator)
- 外观模式(Facade)
- 享元模式(Flyweight)
- 代理模式(Proxy)
行为型模式
- 职责链模式(Chain of Responsibility)
- 命令模式(Command)
- 解释器模式(Interpreter)
- 迭代器模式(Iterator)
- 中介者模式(Mediator)
- 备忘录模式(Memento)
- 观察者模式(Observer)
- 状态模式(State)
- 策略模式(Strategy)
- 模板方法模式(Template Method)
- 访问者模式(Visitor)
下面开始介绍常用的设计模式,讲解三大工厂
1、简单工厂模式
该模式虽然不属于23种设计模式,但是为了后面的引入,这个需要说说
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式 ;在简单工厂模式中,可以根据参数的不同返回不同类的实例 ;简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类
案例:使用简单工厂模式设计一个可以创建不同几何形状的绘图工具,每个几何图形都要有绘制draw()和擦除erase()两个方法,要求在绘制不支持的几何图形时,提示一个UnSupportedShapeExceptionmoqqwrr
案例代码实现
//抽象产品Shape
interface Shape {
public void draw();
public void erase();
}
//具体产品Circle
class Circle implements Shape {
@Override
public void draw() {
System.out.println("圆形在绘制");
}
@Override
public void erase() {
System.out.println("圆形在擦除");
}
}
//具体产品Rectangle
class Rectangle implements Shape{
@Override
public void draw() {
System.out.println("现在是方形在绘制");
}
@Override
public void erase() {
System.out.println("现在是方形在擦除");
}
}
//具体产品Triangle
class Triggle implements Shape{
@Override
public void draw() {
System.out.println("三角形在绘制");
}
@Override
public void erase() {
System.out.println("三角形在擦除");
}
}
//工厂
class ShapeFactory {
public static Shape createShape(String des) throws UnSupportedShapeException {
if(des.equals("t")) {
return new Triggle();
}
else if(des.equals("c")) {
return new Circle();
}
else if(des.equals("r")) {
return new Rectangle();
}
else {
throw new UnSupportedShapeException("该几何图形不支持");
}
}
}
//自定义异常类
class UnSupportedShapeException extends Exception {
public UnSupportedShapeException(String message) {
super(message);
}
}
//客户端测试类
public class lab1_1
{
public static void main(String args[])
{
try
{
Shape shape;
shape=ShapeFactory.createShape("a");
shape=ShapeFactory.createShape("t");
// shape=ShapeFactory.createShape("r");
// shape=ShapeFactory.createShape("c");
shape.draw();
shape.erase();
}
catch(UnSupportedShapeException e)
{
System.out.println(e.getMessage());
}
}
}
简单工厂优点:
- 实现了对象创建和使用的分离
- 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可
- 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性
简单工厂缺点:
- 工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响,违反单一职责原则
- 增加系统中类的个数(引入了新的工厂类),增加了系统的复杂度和理解难度
- 系统扩展困难,一旦添加新产品不得不修改工厂逻辑,违反开闭原则
- 由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构,工厂类不能得到很好地扩展
2、工厂方法
模式定义:在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
案例:某系统日志记录器要求支持多种日志记录方式,如文件记录、数据库记录等,且用户可以根据要求动态选择日志记录方式
案例代码
//日志记录器接口:抽象产品Log
abstract class Log{
public abstract void writeLog();
}
//文件日志记录器:具体产品FileLog
class FileLog extends Log{
@Override
public void writeLog() {
System.out.println("使用文件记录日志");
}
}
//数据库日志记录器:具体产品DatabaseLog
class DatabaseLog extends Log{
@Override
public void writeLog() {
System.out.println("使用数据库记录日志");
}
}
//日志记录器工厂接口:抽象工厂LogFactory
abstract class LogFactory{
public abstract Log createLog();
}
//文件日志记录器工厂类:具体工厂FileLogFactory
class FileLogFactory extends LogFactory{
@Override
public Log createLog() {
System.out.println("使用文件工厂");
return new FileLog();
}
}
//数据库日志记录器工厂类:具体工厂DatabaseLogFactory
class DatabaseLogFactory extends LogFactory{
@Override
public Log createLog() {
System.out.println("使用数据库工厂");
return new DatabaseLog();
}
}
//客户端测试类
public class lab1_2
{
public static void main(String args[])
{
LogFactory factory;
Log log;
factory = new FileLogFactory();
log = factory.createLog();
log.writeLog();
factory=new DatabaseLogFactory();
log=factory.createLog();
log.writeLog();
}
}
工厂方法模式优点:
- 工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节
- 能够让工厂自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部
- 在系统中加入新产品时,完全符合开闭原则
工厂方法模式缺点:
- 系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,会给系统带来一些额外的开销
- 增加了系统的抽象性和理解难度
3、抽象工厂模式
模式定义:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。
在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品
案例:某系统为了改进数据库操作的性能,自定义数据库连接对象Connection和语句对象Statement,可针对不同类型的数据库提供不同的连接对象和语句对象,如提供Oracle或SQL Server专用连接类和语句类,而且用户可以通过配置文件等方式根据实际需要动态更换系统数据库。
案例代码
//数据库连接接口:抽象产品Connection
interface Connection{
public void connect();
}
//Oracle数据库连接类:具体产品OracleConnection
class OracleConnection implements Connection{
@Override
public void connect() {
System.out.println("Oracle数据库正在连接");
}
}
//MySQL数据库连接类:具体产品MySQLConnection
class MySQLConnection implements Connection{
@Override
public void connect() {
System.out.println("MySQL数据库正在连接");
}
}
//数据库语句接口:抽象产品Statement
interface Statement{
public void state();
}
//Oracle数据库语句类:具体产品OracleStatement
class OracleStatement implements Statement{
@Override
public void state() {
System.out.println("Oracle正在使用state语句");
}
}
//MySQL数据库语句类:具体产品MySQLStatement
class MySQLStatement implements Statement{
@Override
public void state() {
System.out.println("MySQL正在使用state语句");
}
}
//数据库工厂接口:抽象工厂DBFactory
interface DBFactory{
public Connection createConnection();
public Statement createStatement();
}
//Oracle数据库工厂:具体工厂OracleFactory
class OracleFactory implements DBFactory{
@Override
public Connection createConnection() {
return new OracleConnection();
}
@Override
public Statement createStatement() {
return new OracleStatement();
}
}
//MySQL数据库工厂:具体工厂MySQLFactory
class MySQLFactory implements DBFactory{
@Override
public Connection createConnection() {
return new MySQLConnection();
}
@Override
public Statement createStatement() {
return new MySQLStatement();
}
}
//客户端测试类
public class lab1_3{
public static void main(String[] args) {
try {
DBFactory factory;
Connection connection;
Statement statement;
factory = new MySQLFactory();
connection =factory.createConnection();
connection.connect();
statement=factory.createStatement();
statement.state();
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
抽象工厂模式优点:
- 隔离了具体类的生成,使得客户端并不需要知道什么被创建
- 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
- 增加新的产品族很方便,无须修改已有系统,符合开闭原则
抽象工厂模式缺点:
- 增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了开闭原则
适用场景:
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节
- 系统中有多于一个的产品族,但每次只使用其中某一产品族
- 属于同一个产品族的产品将在一起使用
- 产品等级结构稳定,在设计完成之后不会向系统中增加新的产品等级结构或者删除已有的产品等级结构