歪说23种设计模式--工厂模式
Posted 秦川以北
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了歪说23种设计模式--工厂模式相关的知识,希望对你有一定的参考价值。
上次小冷说了下单例模式,以及使用场景和五种写法,包括线程安全的不安全的,今天小冷说一下工厂模式
一般遇到这种首先要问几个问题,是什么?为什么这样用,能代理那些好处等等。。。。。。
首先简单的按正常思维去理解一下,什么是工厂模式,小冷理解,打个比方,如果我是一个卖车是厂商,首先我在买车时候会自己生产车的每一个零件吗?显然这种生产每一个零件是可能性是非常小的,因为一辆车他的零件,小到螺丝,大到发动机,东西太多,所以如果自己生产是不可能的,肿么办呢?其实这个厂商完全可以把自己设计好的每一个零件和图纸分给各个工厂,然后在各个厂商中把生产出的零件买回来,自己按照图纸去进行组装,这样技术也不会泄露,又节省了人力成本。这里的每一个生产零件公司其实也可以比作一个个实体类,而这个厂商就是一个工厂,是用来加工每个有共同目的的接口,不知道这样比喻是否正确如有不同还请留言谢谢!
工厂模式:其实它主要是用来实例化有共同接口的类,它可以动态的决定应该实例化哪一个类
工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
使用场景:
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
工厂模式主要分为三种形态:
简单工厂模式(Simple Factory)
工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)
1.简单的工厂模式这里还是使用小汽车的例子做比喻
首先要生产一辆汽车,他有两个很基础的功能,跑和停
创建一个接口并写它这两个方法:
/**
* 简单的工厂模式,抽象的接口
*/
public abstract interface Car {
public void run();
public void stop();
}
有两个厂商要生产它,一个是奔驰另一个是福特,这两个厂商同时实现生产车的这个接口,因为有共同的用途就是生产出来之后要跑和停
//奔驰
public class Benz implements Car{
@Override
public void run() {
System.out.println("Benz---车启动了。。。。。");
}
@Override
public void stop() {
System.out.println("Benz---车停止了。。。。。");
}
}
//福特
public class Ford implements Car {
@Override
public void run() {
System.out.println("Ford---车启动了。。。。。");
}
@Override
public void stop() {
System.out.println("Ford---车停止了。。。。。");
}
}
其次要有一个工厂类来造这两个厂商的车
/**
* 工厂类
*/
public class CarFactory {
public static Car getCar(String type) {
Car car = null;
if("Benz".equals(type)){
car = new Benz();
}
if ("Ford".equals(type)){
car = new Ford();
}
return car;
}
}
然后就是造车卖车开车了,上车车速提上来快
public class Test {
public static void main(String[] args) {
Car c = CarFactory.getCar("Benz");
if (c != null) {
c.run();
c.stop();
} else {
System.out.println("造不了这种汽车。。。");
}
}
}
上面是简单的工厂模式,其实不难理解,就是要想让不同厂商卖车去跑,首先每个厂商有共同的目的目标就是实现有共同方法的接口,然后根据不同的厂商去工厂生产能跑能停的车。
好了下面小冷继续说工厂模式剩下的两种形态
2.工厂方法模式
从上边的简单工厂模式我们可以看出产品的生产太依赖于简单工厂这个核心,一旦简单工厂类出现问题,则整个模式都将受到影响,不利于维护和扩展。
而工厂方法模式通过把工厂类定义为接口,以多态的形式来削弱工厂类的职能,对简单工厂模式进一步的解耦,这相当于是把原本会因为业务代码而庞大的简单工厂类,拆分成了一个个的工厂类,这样代码就不会都耦合在同一个类里了。大大降低了简单工厂模式的一些风险,提高日后的可维护性和可扩展性。
这里用康师傅做比喻
//工厂接口
public interface Factory {
public Product createProduct();
}
//产品接口
public interface Product{}
//饮料和泡面实现了Product接口
public class Drinks implements Product {
public Drinks() {
system.out.println("生产饮料");
}
}
public class Noodles implements Product {
public Noodles() {
system.out.println("生产泡面");
}
}
//具体工厂类实现了工厂接口
//生产饮料的工厂
public class DrinksFactory implements Factory{
public Product createProduct(){
return new Drinks();
}
}
//生产泡面的工厂
public class NoodlesFactory implements Factory{
public Product createProduct(){
return new Noodles();
}
}
//客户端代码
public class Client {
public static void main(String[] args) throws Exception {
// 使用反射机制实例化工厂对象,因为字符串是可以通过变量改变的
//反射方法的实质是在对象实例化的时候传引用,将程序由编译时转为运行时,通过字符串变量来处理,去除了switch判断的麻烦
Factory drinksFactory = (Factory) Class.forName("com.banana.factory.DrinksFactory ").newInstance();
Factory noodlesFactory = (Factory) Class.forName("com.banana.factory.NoodlesFactory").newInstance();
// 通过工厂对象创建相应的实例对象
Product drinks = drinksFactory.createProduct();
Product noodles = noodlesFactory.createProduct();
}
}
优点:不同产品的实例对象的创建,没有耦合在同一个工厂类里,实现了对简单工厂模式的解耦,并且遵循了“发放-封闭”原则。
缺点:每增加一个产品类,就需要增加一个对应的工厂类,增加了额外的开发量。
3.抽象工厂模式
这里还拿汽车做比喻
以我的理解,抽象工厂模式和工厂方法模式的区别就在于,在工厂方法模式下一个工厂只能生产同类同品的产品(同一规格的一类产品),而在抽象工厂模式下一个工厂可以生产多类同品的产品(同一规格的多类产品,也可以称作一系列产品)。
// 抽象产品角色
public interface Moveable {
void run();
}
// 抽象工厂
public abstract class VehicleFactory {
abstract Moveable create();
}
// 具体工厂
public class BroomFactory extends VehicleFactory {
public Moveable create() {
return new Broom();
}
}
// 具体工厂
public class PlaneFactory extends VehicleFactory {
public Moveable create() {
return new Plane();
}
}
// 具体产品角色
public class Broom implements Moveable {
@Override
public void run() {
System.out.println("broom.....");
}
}
// 具体产品角色
public class Plane implements Moveable {
@Override
public void run() {
System.out.println("plane....");
}
}
// 测试类
public class Test {
public static void main(String[] args) {
VehicleFactory factory = new BroomFactory();
Moveable m = factory.create();
m.run();
}
}
优点:当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
这里用到一个很重要的知识点就是多态,这是重点要划住要考,多态这里解释一下是类的不同状态,还可以解释为父类的引用指向子类的对象。
明天教师节这里小冷像所有有德有才的老师致以诚挚和亲切的问候,老师好!!!
以上是关于歪说23种设计模式--工厂模式的主要内容,如果未能解决你的问题,请参考以下文章