设计模式是思想,灵活使用会很大程度上减少开发的难度,拓展框架和程序的时候会很方便
创建模式分为:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
1.简单工厂模式(不属于23种设计模式)
虽然简单工厂模式不属于23种设计模式,但是它是工厂方法模式、抽象工厂模式的基础。要理解这两种模式就要从简单工厂模式开始看起。
1.1、普通简单工厂模式
先设想一个场景,有一个工厂,工厂下面有两个车间一个生产汽车一个生产摩托车。
简单粗暴直接上代码先创建一个车间接口:
//车间的定义(一个接口,抽象出,车间有一个建造动作)
public interface Workshop {
public void production();
}
接着建造2个有具体动作的实体工厂:
public class CarWorkshop implements Workshop{
public void production(){
System.out.println("生产汽车");
}
}
public class MotorcycleWorkshop implements Workshop{
public void production(){
System.out.println("生产摩托车");
}
}
然后创建工厂可以开始生产了:
public class Factory {
//生产方法,传入不同的类型,选择生产实体类。
public Workshop produce(String type) {
if ("car".equals(type)) {
return new CarWorkshop();
} else if ("motorcycle".equals(type)) {
return new MotorcycleWorkshop();
} else {
System.out.println("请输入正确的类型!");
return null;
}
}
}
//实现类
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new Factory();
Workshop sender = factory.produce("car");
sender.production();
}
}
//控制台输出 : 生产汽车
1.2、多个方法简单工厂模式
在简单工厂的模式下发现,如果传入参数有出入,就不能正确的创建工厂,所以做出修改,创建两个方法用不同的方法来创建工厂。
在工厂类做出修改:
public class Factory {
//拆开方法,调用不同方法直接创建实体
public Workshop produceCar() {
return new CarWorkshop();
}
public Workshop produceMotorcycle() {
return new MotorcycleWorkshop();
}
}
//测试代码:
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new Factory();
factory.produceMotorcycle().production();
}
}
//输出:生产摩托车
1.3、静态方法简单工厂模式
在多个方法模式下继续优化,把方法写成静态的,能更加方便的创建实体。
public class Factory {
public static Workshop produceCar() {
return new CarWorkshop();
}
public static Workshop produceMotorcycle() {
return new MotorcycleWorkshop();
}
}
//测试代码:
public class FactoryTest {
public static void main(String[] args) {
Factory.produceMotorcycle().production();
}
}
//输出:生产摩托车
简单工厂介绍完毕,接下来就可以研究设计模式了。
2工厂方法模式
简单工厂模式有一个缺点,实体的创建都依赖于Factory工厂类,这就遇到一个问题–要拓展程序(有新的车间加入了工厂)必须要修改工厂类,这就违背了设计模式的闭包原则(在程序需要进行拓展的时候,不能去修改原有的代码)。
解决方式,抽象创建过程,把工厂抽象出来,拓展的时候创建一个新的工厂就行,(汽车车间和摩托车车间分成两个工厂分开生产)。
这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
两个车间代码保持不动,抽象工厂,上代码:
public interface Factory {
//工厂抽象出生产车间方法
public Workshop produceWorkshop();
}
//写两个实现方法:
public class CarFactory implements Factory{
@Override
public Workshop produceWorkshop(){
return new CarWorkshop();
}
}
public class MotorcycleFactory implements Factory{
@Override
public Workshop produceWorkshop(){
return new MotorcycleWorkshop();
}
}
//测试:
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new MotorcycleFactory();
factory.produceWorkshop().production();
}
}
//输出:生产摩托车
总结一下:如果要拓展,新增一个实体(生产自行车的车间),只需要新实现一个Workshop类(车间实体)和一个Factory(工厂实体),不需要修改原来的任何代码。
4、抽象工厂模式
抽象工厂比较难理解,先贴一下百度百科的介绍:
抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用于产品族的构建。抽象工厂是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。
工厂模式中的每一个形态都是针对一定问题的解决方案,工厂方法针对的是多个产品系列结构;而抽象工厂模式针对的是多个产品族结构,一个产品族内有多个产品系列。
抽象工厂模式的主要角色如下:
1.抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
2.具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
3.抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
4.具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
看了很多理论知识,个人认为抽象工厂的核心就是简单工厂的组合、抽象。抽象工厂可以派生出多个具体工厂类。
上代码,还是具体的工厂车间例子:
/**
* 摩托车抽象
*/
public interface MotorcycleWorkshop{
public void production();
}
/**
* 汽车车间抽象
*/
public interface CarWorkshop{
public void production();
}
/**
*实体类
*/
/**
* 豪华摩托车生产
*/
public class LuxuryMotorcycleWorkshop implements MotorcycleWorkshop{
public void productionMotorcycle(){
System.out.println(" 豪华摩托车生产");
}
}
public class CheapMotorcycleWorkshop implements MotorcycleWorkshop{
public void productionMotorcycle(){
System.out.println("便宜摩托车生产");
}
}
public class CheapCarWorkshop implements CarWorkshop{
public void productionCar(){
System.out.println("便宜汽车车生产");
}
}
public class LuxuryCarWorkshop implements CarWorkshop{
public void productionCar(){
System.out.println("豪华汽车车生产");
}
}
下面是工厂类,组合了生产车间:
public interface Factory {
//工厂抽象出生产车
public CarWorkshop productionCar();
//工厂抽象出生产摩托车
public MotorcycleWorkshop productionMotorcycle();
}
//TK工厂实现类 生产便宜的汽车和贵的摩托车
public class TKFactory implements Factory{
//工厂抽象出生产车
public CarWorkshop productionCar(){
return new CheapCarWorkshop();
}
//工厂抽象出生产摩托车
public MotorcycleWorkshop productionMotorcycle(){
return new LuxuryMotorcycleWorkshop();
}
}
//JR工厂 生产贵的汽车和摩托车
public class JRFactory implements Factory{
//工厂抽象出生产车
public CarWorkshop productionCar(){
return new LuxuryCarWorkshop();
}
//工厂抽象出生产摩托车
public MotorcycleWorkshop productionMotorcycle(){
return new LuxuryMotorcycleWorkshop();
}
}
//测试类
public class FactoryTest {
public static void main(String[] args) {
Factory factory = new JRFactory();
factory.productionCar();
factory.productionMotorcycle()
}
}
可以任意组合车间,从而创建不同的工厂生产。
4、单例模式
概念:
单例对象(Singleton)是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。(比如一个军队出现了多个司令员同时指挥,肯定会乱成一团),所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
目前主流框架大多用到了单例,像spring框架,通过它创建的对象默认都是单例的。很多工具类也会用到单例。
上代码:
//懒汉模式
public class Singleton {
//持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载
private static Singleton instance = null;
//私有构造方法 外部不能创建对象 只能通过调用getInstance()方法
private Singleton() {
}
//初始化方法 第一次调用new单例,后面调用直接返回创建过的对象
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
//饿汉模式
public class Singleton {
//饿汉模式在创建的时候把单例对象写入静态代码块里面
private static Singleton instance = new Singleton();
private Singleton() {
}
//
public static Singleton getInstance() {
return instance;
}
}
5、建造者模式
建造者(Builder)模式的定义:指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者 4 个要素构成。
建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。通俗点来说,工厂模式不关注如何get和set只是返回创建好的对象,建造者模式关心对象如何组装(set)返回的是更具需求组装好的对象。
上代码:
/**
* 产品类
*/
public class Car {
//私有化对象
private String window;
private String wheel;
private String engine;
private String door;
public String getWindow() {
return window;
}
public void setWindow(String window) {
this.window = window;
}
public String getWheel() {
return wheel;
}
public void setWheel(String wheel) {
this.wheel = wheel;
}
public String getEngine() {
return engine;
}
public void setEngine(String engine) {
this.engine = engine;
}
public String getDoor() {
return door;
}
public void setDoor(String door) {
this.door = door;
}
}
/**
* 抽象建造者
*/
public abstract class BuilderCar {
Car car = new Car();
public abstract void buildWindow();
public abstract void buildWheel();
public abstract void buildEngine();
public abstract void buildDoor();
//返回产品对象
public Car getCar() {
return car;
}
}
/**
* 具体建造者
*/
public class TXBuilderCar extends BuilderCar{
public void buildWindow(){
car.setWindow("建造窗户");
}
public void buildWheel(){
car.setWheel("建造轮子");
}
public void buildEngine(){
car.setEngine("建造发动机");
}
public void buildDoor(){
car.setDoor("建造门");
}
}
/**
* 指挥者
*/
public class Commander {
private BuilderCar car;
public Commander(BuilderCar car) {
this.car = car;
}
//产品构建与组装方法
public Car construct() {
car.buildDoor();
car.buildEngine();
car.buildWheel();
return car.getCar();
}
}
/**
* 测试
*/
public class Test {
public static void main(String[] args) {
BuilderCar builder = new TXBuilderCar();
Commander commander = new Commander(builder);
Car car = commander.construct();
System.out.println( car.toString());
}
}
//输出 Car{window='null', wheel='建造轮子', engine='建造发动机', door='建造门'}
简单的建造者模式就是这样的。
6原型模式
原型模式使用原型实例指定创建对象的种类,并且通过拷贝原型对象创建新的对象。
通俗一点来说就是对象已经创建好了,原型模式创建对象只是拷贝原型。
上代码:
public class Prototype implements Cloneable {
/**
* 省略了一堆内部参数 原型模式重点在克隆
* @return
* @throws CloneNotSupportedException
*/
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
}
克隆的方式在java中有两种 浅克隆和深克隆
浅克隆是直接调用而在Object类中的clone(),clone()是native的。
深克隆是使用二进制克隆。
浅克隆非常简单就不多叙述了。
深克隆代码
public class Prototype implements Cloneable {
/**
* 省略了一堆内部参数 原型模式重点在克隆
* @return
* @throws CloneNotSupportedException
*/
public Object clone() throws CloneNotSupportedException {
Prototype proto = (Prototype) super.clone();
return proto;
}
/* 深克隆 */
public Object deepClone() throws IOException, ClassNotFoundException {
/* 写入当前对象的二进制流 */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
/* 读出二进制流产生的新对象 */
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
使用二进制来产生对象。
参考文章