设计模式--工厂模式
工厂模式
简单工厂模式
基本介绍:
(1) 简单工厂模式是属于创建型模式 是工厂模式的一种 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简单工厂模式是工厂模式家族中最简单实用的模式
(2) 简单工厂模式: 定义了一个创建对象的类 由这个类来封装实例化对象的行为(代码)
(3) 在软件开发时 当我们要用到大量的创建某种 某类或者某批对象时 就会用到工厂模式
定义:定义了一个创建对象的类,由这个类来封装实例化对象的行为。
这里以可乐工厂为例,首先创建一个总的类型 可乐,然后再创建 可口可乐,百事可乐,非常可乐三个实例,三个实例继承自可乐 通过可乐工厂来直接生成三种不同的可乐
可乐类
@Data
@Accessors(chain = true)
public class Cola {private String name;private Integer price;@Overridepublic String toString() {return "Cola{" +"name='" + name + '\\'' +", price=" + price +'}';}
}
可口可乐
@Data//可口可乐
@Accessors(chain = true)
public class ColaCola extends Cola{
}
百事可乐
@Data //百事可乐
@Accessors(chain = true)
public class Pepsi extends Cola{
}
非常可乐
//非常可乐
@Accessors(chain = true)
@Data
public class VeryCola extends Cola{
}
可乐工厂
public class ColaFactory {public Cola CreateCola(String type){Cola cola = null;Optional<Cola> optionalCola = Optional.ofNullable(cola);cola = optionalCola.orElseGet(()->{if(type.equals("kekou")) return new ColaCola().setName("可口可乐");else if(type.equals("baishi")) return new Pepsi().setName("百事可乐");else if(type.equals("feichang")) return new VeryCola().setName("非常可乐");else return new Cola().setName("可乐");});return cola;}public static void main(String[] args) {ColaFactory colaFactory = new ColaFactory();System.out.println(colaFactory.CreateCola("feichang").getName());}
}
测试结果:
简单工厂存在的问题与解决方法:
简单工厂模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了开闭原则,所以,从设计角度考虑,有一定的问题,如何解决?我们可以定义一个创建对象的抽象方法并创建多个不同的工厂类实现该抽象方法,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。这种方法也就是我们接下来要说的工厂方法模式。
工厂方法模式
基本介绍:
工厂方法模式设计方案: 将可乐项目的实例化功能抽象成抽象方法,在不同类型的可乐子类中进行具体的实现
定义:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。
这里还是用可乐工厂,这次有两个可乐工厂,上海工厂和杭州工厂 如果用简单工厂模式的话 我们要去修改工厂代码 并且会增加一堆if else 语句 而工厂模式克服了简单工厂要修改代码的缺点 这里会直接创建两个工厂
上海百事可乐
@Data
@Accessors(chain = true)
public class ShPesi extends Cola {
}
上海可口可乐
@Data
@Accessors(chain = true)
public class ShColaCola extends Cola {
}
杭州百事可乐
@Data
@Accessors(chain = true)
public class HzPesi extends Cola {
}
杭州可口可乐
@Data
@Accessors(chain = true)
public class ShColaCola extends Cola {
}
杭州工厂
public class HzFactory extends OrderCola{@OverrideCola createCola(String type) {Cola cola = null;Optional<Cola> optionalCola = Optional.ofNullable(cola);cola = optionalCola.orElseGet(()->{if(type.equals("kekou")) return new HzColaCola().setName("杭州可口可乐");else if(type.equals("baishi")) return new HzPesi().setName("杭州百事可乐");else return new Cola().setName("可乐");});return cola;}
}
上海工厂
public class ShFactory extends OrderCola{@OverrideCola createCola(String type) {Cola cola = null;Optional<Cola> optionalCola = Optional.ofNullable(cola);cola = optionalCola.orElseGet(()->{if(type.equals("kekou")) return new ShColaCola().setName("上海可口可乐");else if(type.equals("baishi")) return new ShPesi().setName("上海百事可乐");else return new Cola().setName("可乐");});return cola;}
}
可乐工厂
@Data
@Accessors(chain = true)
public abstract class OrderCola {abstract Cola createCola(String type);public static void main(String[] args) {OrderCola orderCola = new ShFactory();System.out.println(orderCola.createCola("baishi").getName());}
}
测试结果
解决了简单工厂模式的问题:增加一个新的可乐产地南京,只要增加一个南京工厂类(此处省略,参考上海工厂或杭州工厂)
其实这个模式的好处就是,如果你现在想增加一个功能,只需做一个实现类就OK了,无需去改动现成的代码。这样做,拓展性较好!
工厂方法存在的问题与解决方法:
客户端需要创建类的具体的实例。简单来说就是用户要订上海工厂的可乐,他必须去上海工厂,想订杭州工厂的可乐,必须去杭州工厂。 当上海工厂和杭州工厂发生变化了,用户也要跟着变化,这无疑就增加了用户的操作复杂性。为了解决这一问题,我们可以把工厂类抽象为接口,用户只需要去找默认的工厂提出自己的需求(传入参数),便能得到自己想要产品,而不用根据产品去寻找不同的工厂,方便用户操作。这也就是我们接下来要说的抽象工厂模式。
抽象工厂模式
基本介绍:
(1) 抽象工厂模式::定义了一个接口用于创建相关或有依赖关系的对象簇,而无需明确指定具体类。
(2) 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合
(3) 从设计层面看 抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)
(4) 将工厂抽象成两层 抽象工厂和具体实现的工厂子类 程序猿可以根据创建对象类型使用相对应的工厂子类 这样将单个的简单工厂类变成了工厂簇 更利于代码的维护和扩展
工厂接口:
public interface ColaFactoryIn {Cola createCola(String type);static void main(String[] args) {ColaFactoryIn sh = new ShangHaiFactory();Cola cola = sh.createCola("baishi");System.out.println(cola.getName());ColaFactoryIn hz = new HangZhouFactory();Cola hzcola = hz.createCola("kekou");System.out.println(hzcola.getName());}
}
上海工厂实现:
public class ShangHaiFactory implements ColaFactoryIn{@Overridepublic Cola createCola(String type) {Cola cola = null;Optional<Cola> optionalCola = Optional.ofNullable(cola);cola = optionalCola.orElseGet(()->{if(type.equals("kekou")) return new ShColaCola().setName("上海可口可乐");else if(type.equals("baishi")) return new ShPesi().setName("上海百事可乐");else return new Cola().setName("可乐");});return cola;}
}
杭州工厂实现:
public class HangZhouFactory implements ColaFactoryIn {@Overridepublic Cola createCola(String type) {Cola cola = null;Optional<Cola> optionalCola = Optional.ofNullable(cola);cola = optionalCola.orElseGet(()->{if(type.equals("kekou")) return new HzColaCola().setName("杭州可口可乐");else if(type.equals("baishi")) return new HzPesi().setName("杭州百事可乐");else return new Cola().setName("可乐");});return cola;}
}
测试:
工厂模式适用的场合
大量的产品需要创建,并且这些产品具有共同的接口 。
三种工厂模式的使用选择
简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)
抽象工厂 :用来生产不同产品族的全部产品。(支持拓展增加产品;支持增加产品族)
简单工厂的适用场合:只有工厂(只有这一个等级),并且这个工厂只生产三种类型的可乐:可口,非常,百事(固定产品)。
工厂方法的适用场合:现在不光有上海工厂,还增设了杭州工厂(仍然是同一等级结构,但是支持了产品的拓展),这两个工厂依然只生产三种类型的可乐:可口,百事,非常(固定产品)。
抽象工厂的适用场合:不光增设了杭州工厂(仍然是同一等级结构,但是支持了产品的拓展),这两个工厂还增加了一种新的类型的可乐:爽口可乐(增加产品族)。
所以说抽象工厂就像工厂,而工厂方法则像是工厂的一种产品生产线。因此,我们可以用抽象工厂模式创建工厂,而用工厂方法模式创建生产线。比如,我们可以使用抽象工厂模式创建上海工厂和杭州工厂,使用工厂方法实现各种可乐的生产。
工厂模式在 jdk中的应用分析
jdk中的Calendar类中 就使用了简单工厂模式
Calendar.ggetInstance 是一个获取实例的静态方法
总结一下三种模式:
简单工厂模式就是建立一个实例化对象的类,在该类中对多个对象实例化。工厂方法模式是定义了一个创建对象的抽象方法,由子类决定要实例化的类。这样做的好处是再有新的类型的对象需要实例化只要增加子类即可。抽象工厂模式定义了一个接口用于创建对象族,而无需明确指定具体类。抽象工厂也是把对象的实例化交给了子类,即支持拓展。同时提供给客户端接口,避免了用户直接操作子类工厂。
工厂模式的意义是将实例化对象的代码提取出来 放到一个类中统一管理和维护 达到和主项目的依赖关系的解耦 从而提高项目的扩展和维护性
设计模式的依赖抽象原则:
(1) 创建对象实例时 不要直接new类 而是把这个new类的动作放在一个工厂的方法中并返回 变量最好不要直接持有具体类的引用
(2) 不要让类继承具体类 而是继承抽象类或者是实现inerface(接口)
(3) 不要覆盖基类中已经实现的方法