定义:定义了一个创建对象的类,由这个类来封装实例化对象的行为。
举例:(我们举一个pizza工厂的例子)
pizza工厂一共生产三种类型的pizza(披萨):chesse(奶酪),pepper(胡椒),greak(格里克)。通过工厂类(SimplePizzaFactory)实例化这三种类型的对象。类图如下:
工厂类的代码:
public class SimplePizzaFactory {
public Pizza CreatePizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new CheesePizza();
} else if (ordertype.equals("greek")) {
pizza = new GreekPizza();
} else if (ordertype.equals("pepper")) {
pizza = new PepperPizza();
}
return pizza;
}
}
简单工厂存在的问题与解决方法: 简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了开闭原则,所以,从设计角度考虑,有一定的问题,如何解决?我们可以定义一个创建对象的抽象方法并创建多个不同的工厂类实现该抽象方法,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。这种方法也就是我们接下来要说的工厂方法模式。
1.2 工厂方法模式定义:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
举例:(我们依然举pizza工厂的例子,不过这个例子中,pizza产地有两个:伦敦和纽约)。添加了一个新的产地,如果用简单工厂模式的的话,我们要去修改工厂代码,并且会增加一堆的if else语句。而工厂方法模式克服了简单工厂要修改代码的缺点,它会直接创建两个工厂,纽约工厂和伦敦工厂。类图如下:
OrderPizza中有个抽象的方法:
abstract Pizza createPizza();
两个工厂类继承OrderPizza并实现抽象方法:
public class LDOrderPizza extends OrderPizza {
Pizza createPizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
public class NYOrderPizza extends OrderPizza {
Pizza createPizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new NYCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new NYPepperPizza();
}
return pizza;
}
}
、通过不同的工厂会得到不同的实例化的对象,PizzaStroe的代码如下:
public class PizzaStroe {
public static void main(String[] args) {
OrderPizza mOrderPizza;
mOrderPizza = new NYOrderPizza();
}
}
解决了简单工厂模式的问题:增加一个新的pizza产地(北京),只要增加一个BJOrderPizza类:
public class BJOrderPizza extends OrderPizza {
Pizza createPizza(String ordertype) {
Pizza pizza = null;
if (ordertype.equals("cheese")) {
pizza = new LDCheesePizza();
} else if (ordertype.equals("pepper")) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
其实这个模式的好处就是,如果你现在想增加一个功能,只需做一个实现类就OK了,无需去改动现成的代码。这样做,拓展性较好!
工厂方法存在的问题与解决方法:客户端需要创建类的具体的实例。简单来说就是用户要订纽约工厂的披萨,他必须去纽约工厂,想订伦敦工厂的披萨,必须去伦敦工厂。 当伦敦工厂和纽约工厂发生变化了,用户也要跟着变化,这无疑就增加了用户的操作复杂性。为了解决这一问题,我们可以把工厂类抽象为接口,用户只需要去找默认的工厂提出自己的需求(传入参数),便能得到自己想要产品,而不用根据产品去寻找不同的工厂,方便用户操作。这也就是我们接下来要说的抽象工厂模式。
1.3 抽象工厂模式定义定义了一个接口用于创建相关或有依赖关系的对象族,而无需明确指定具体类。
举例1(我们依然举pizza工厂的例子,pizza工厂有两个:纽约工厂和伦敦工厂)。类图如下:
工厂的接口:
public interface AbsFactory {
Pizza CreatePizza(String ordertype);
}
工厂的实现:
public class LDFactory implements AbsFactory {
@Override
public Pizza CreatePizza(String ordertype) {
Pizza pizza = null;
if ("cheese".equals(ordertype)) {
pizza = new LDCheesePizza();
} else if ("pepper".equals(ordertype)) {
pizza = new LDPepperPizza();
}
return pizza;
}
}
PizzaStroe的代码如下:
public class PizzaStroe {
public static void main(String[] args) {
OrderPizza mOrderPizza;
mOrderPizza = new OrderPizza("London");
}
}
解决了工厂方法模式的问题:在抽象工厂中PizzaStroe中只需要传入参数就可以实例化对象。
举例2(有一个连接操作数据库的抽象工厂,定义连接操作数据库的规范,有两个产品族,分别是mysql产品族和oracle产品族)。类图如下:
具体实现如下:
public class AbstractFactoryTest {
public static void main(String[] args) {
//调用Mysql连接及操作。
IConnectionUtils iConnectionUtils=new MysqlCommandUtils();
IConnection connection = iConnectionUtils.getConnection();
connection.connect();
ICommand command = iConnectionUtils.getCommand();
command.command();
//调用oracle连接及操作。
IConnectionUtils iConnectionUtils1=new OracleCommandUtils();
IConnection connection1 = iConnectionUtils1.getConnection();
connection1.connect();
ICommand command1 = iConnectionUtils1.getCommand();
command1.command();
}
}
//定义规范接口
interface IConnection{
void connect();
}
interface ICommand{
void command();
}
interface IConnectionUtils{
IConnection getConnection();
ICommand getCommand();
}
//mysql 连接及操作的具体实现
class MysqlConnection implements IConnection{
@Override
public void connect() {
System.out.println("mysql connected.");
}
}
class MysqlCommand implements ICommand{
@Override
public void command() {
System.out.println("mysql command.");
}
}
class MysqlCommandUtils implements IConnectionUtils{
@Override
public IConnection getConnection() {
return new MysqlConnection();
}
@Override
public ICommand getCommand() {
return new MysqlCommand();
}
}
//oracle 连接及操作的具体实现
class OracleConnection implements IConnection{
@Override
public void connect() {
System.out.println("oracle connection.");
}
}
class OracleCommand implements ICommand{
@Override
public void command() {
System.out.println("oracle command.");
}
}
class OracleCommandUtils implements IConnectionUtils{
@Override
public IConnection getConnection() {
return new OracleConnection();
}
@Override
public ICommand getCommand() {
return new OracleCommand();
}
}
模拟真实jdbc连接扩展带参数和返回值的代码:
//定义规范接口
interface IConnection {
String connect(String url, String username, String password);
boolean disconnect();
}
interface ICommand {
String command(String sql);
int add(String sql);
boolean delete(String sql);
String select(String sql);
boolean update(String sql);
}
interface IConnectionUtils {
IConnection getConnection();
ICommand getCommand();
}
/**
* 设计模式-抽象工厂模式
*/
public class AbstractFactoryTest {
public static void main(String[] args) {
//调用mysql连接及操作。
IConnectionUtils iConnectionUtils = new MysqlCommandUtils();
IConnection connection = iConnectionUtils.getConnection();
connection.connect("jdbc:mysql://10.16.158.90:3306/db1", "root", "123456");
ICommand command = iConnectionUtils.getCommand();
command.command("show databases");
command.add("insert into test ");
command.select("select * from test");
command.update("update test ");
command.delete("delete from test");
connection.disconnect();
//调用oracle连接及操作。
IConnectionUtils iConnectionUtils1 = new OracleCommandUtils();
IConnection connection1 = iConnectionUtils1.getConnection();
connection1.connect("jdbc:thin://10.16.158.90:3306/db1", "root", "123456");
ICommand command1 = iConnectionUtils1.getCommand();
command1.command("show databases");
command1.add("insert into test ");
command1.select("select * from test");
command1.update("update test ");
command1.delete("delete from test");
connection1.disconnect();
}
}
//mysql 连接及操作的具体实现
class MysqlConnection implements IConnection {
@Override
public String connect(String url, String username, String password) {
System.out.println("mysql connected." url username password);
return url username password;
}
@Override
public boolean disconnect() {
System.out.println("mysql disconnected.");
return true;
}
}
class MysqlCommand implements ICommand {
@Override
public String command(String sql) {
System.out.println("mysql:command:" sql);
return sql;
}
@Override
public int add(String sql) {
System.out.println("mysql:add:" sql);
return 0;
}
@Override
public boolean delete(String sql) {
System.out.println("mysql:delete:" sql);
return true;
}
@Override
public String select(String sql) {
System.out.println("mysql:select:" sql);
return sql;
}
@Override
public boolean update(String sql) {
System.out.println("mysql:update:" sql);
return true;
}
}
class MysqlCommandUtils implements IConnectionUtils {
@Override
public IConnection getConnection() {
return new MysqlConnection();
}
@Override
public ICommand getCommand() {
return new MysqlCommand();
}
}
//oracle 连接及操作的具体实现
class OracleConnection implements IConnection {
@Override
public String connect(String url, String username, String password) {
System.out.println("oracle connected." url username password);
return url username password;
}
@Override
public boolean disconnect() {
System.out.println("oracle disconnected.");
return true;
}
}
class OracleCommand implements ICommand {
@Override
public String command(String sql) {
System.out.println("oracle command: " sql);
return sql;
}
@Override
public int add(String sql) {
System.out.println("oracle add: " sql);
return 0;
}
@Override
public boolean delete(String sql) {
System.out.println("oracle delete: " sql);
return false;
}
@Override
public String select(String sql) {
System.out.println("oracle select:" sql);
return sql;
}
@Override
public boolean update(String sql) {
System.out.println("oracle update:" sql);
return false;
}
}
class OracleCommandUtils implements IConnectionUtils {
@Override
public IConnection getConnection() {
return new OracleConnection();
}
@Override
public ICommand getCommand() {
return new OracleCommand();
}
}
应用场景
程序需要处理不同系列的相关产品,但是您不希望它依赖于这些产品的具体类时可以使用抽象工厂
优点1.可以确信你从工厂得到的产品彼此是兼容的。
2.可以避免具体产品和客户端代码之间的紧密耦合。
3.符合单一职责原则
4.符合开闭原则
JDK源码中的应用java.sql.connection
java.sql.Driver
1.4 工厂模式适用的场合
大量的产品需要创建,并且这些产品具有共同的接口 。
1.5 三种工厂模式的使用选择简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
抽象工厂 :用来生产不同产品族的全部产品。(支持拓展增加产品;支持增加产品族)
简单工厂的适用场合:只有伦敦工厂(只有这一个等级),并且这个工厂只生产三种类型的pizza:chesse,pepper,greak(固定产品)。
工厂方法的适用场合:现在不光有伦敦工厂,还增设了纽约工厂(仍然是同一等级结构,但是支持了产品的拓展),这两个工厂依然只生产三种类型的pizza:chesse,pepper,greak(固定产品)。
抽象工厂的适用场合:不光增设了纽约工厂(仍然是同一等级结构,但是支持了产品的拓展),这两个工厂还增加了一种新的类型的pizza:chinese pizza(增加产品族)。
所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线。因此,我们可以用抽象工厂模式创建工厂,而用工厂方法模式创建生产线。比如,我们可以使用抽象工厂模式创建伦敦工厂和纽约工厂,使用工厂方法实现cheese pizza和greak pizza的生产。类图如下:
总结一下三种模式:
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved