项目越做越大,代码越写越多,代码重复的问题肯定大家都遇到过,也都反感过。那如何让我们写的代码变的易维护、可拓展、轻巧灵活、可复用呢,说到这里就不得不提今天的话题:设计模式。废话少说,进入正题~
1、简单工厂模式
(一)、定义:
提供一个创建对象实例的功能,而无须关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
(二)、结构:
比如有家代工厂可以代工生产美的和格力的空调。工厂收到格力指令,就生产格力空调;收到美的指令,就生产美的空调。生产完工后,直接发货到采购商,不需要美的或格力再超心生产流程的问题。
(三)、代码演示:
/**
* 简单工厂模式
*/
public class SimpleFactory {
public final static String MIDEA_CODE = "0";
public final static String GREE_CODE = "1";
public AirConditioner createAirConditioner(String code){
AirConditioner airConditioner;
switch (code){
case MIDEA_CODE:
airConditioner = new MideaAirConditioner();
break;
case GREE_CODE:
airConditioner = new GreeAirConditioner();
break;
default:
airConditioner = null;
}
assert airConditioner != null:"输入编码有误...";
makeAirConditioner(airConditioner.getClass().getSimpleName());
return airConditioner;
}
private void makeAirConditioner(String simpleName) {
System.out.println(simpleName +"正在赶工中...");
}
}
/**
* @Description: 空调对象
*/
public class AirConditioner {
private Integer id;
private String modelNumber;
private String spec;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getModelNumber() {
return modelNumber;
}
public void setModelNumber(String modelNumber) {
this.modelNumber = modelNumber;
}
public String getSpec() {
return spec;
}
public void setSpec(String spec) {
this.spec = spec;
}
@Override
public String toString() {
return "AirConditioner{" +
"id=" + id +
", modelNumber='" + modelNumber + '\'' +
", spec='" + spec + '\'' +
'}';
}
}
/**
* @Description: 格力空调
*/
public class GreeAirConditioner extends AirConditioner{
}
/**
* @Description: 美的空调
*/
public class MideaAirConditioner extends AirConditioner{
}
public class SimpleFactoryTest {
@Test
public void test (){
SimpleFactory factory = new SimpleFactory();
AirConditioner airConditioner = factory.createAirConditioner(GREE_CODE);
System.out.println("上架空调:"+ airConditioner);
}
}
2、工厂方法模式
(一)、定义:
定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Mothod是一个类的实例化延申到其子类。
(二)、结构:
相比简单工厂模式,工厂方法模式下想要生产空调,不在需要代工厂生产。美的或格力说代工厂生产的空调质量不够硬,我们自己来生产。代工厂转而成为了美的和格力空调的承销商,对外发布出售美的空调和格力空调。想要美的空调直接告诉美的去生产美的空调,想要格力空调直接告诉格力去生产格力空调。
(三)、代码演示
/**
* @Description: 上架空调
*/
public interface ShelfAirConditioner {
/**
* @description: 生产空调
*
* @param: code
* @return: AirConditioner
**/
public abstract AirConditioner createAirConditioner();
}
/**
* @Description: 上架格力空调
*/
public class ShelfGreeAirConditioner implements ShelfAirConditioner {
@Override
public AirConditioner createAirConditioner() {
System.out.println("正在赶工格力空调.....");
return new GreeAirConditioner();
}
}
/**
* @Description: 上架美的空调
*/
public class ShelfMideaAirConditioner implements ShelfAirConditioner {
@Override
public AirConditioner createAirConditioner() {
System.out.println("正在赶工美的空调.....");
return new MideaAirConditioner();
}
}
3、抽象工厂模式
(一)、定义:
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
(二)、结构:
还是对比上面的例子,抽象工厂模式就好比,代工厂转承销商后搞大了。然后制定了一套严格的生产空调的流程。美的和格力继续享受代理销售的服务,必须验证按照代工厂的流程生产自己去生产。想要美的空调还是直接告诉美的去生产美的空调,想要格力空调直接告诉格力去生产格力空调。
(三)、代码演示:
定义一系列流程接口
/**
* 采购接口
*/
public interface IPurchase {
void purchase();
}
/**
* 生产接口
*/
public interface IProduct {
void make();
}
/**
* 加工接口
*/
public interface IProcess {
void processing();
}
/**
* @Description: 抽象工厂模式
*/
public interface AbstractFactory {
// 1、采购原材料
IPurchase getPurchase();
// 2、生产空调
IProduct makeProduct();
// 3、精加工
IProcess processing();
}
编写一种实现
/**
* @Description: 格力采购
*/
public class GreePurchase implements IPurchase {
@Override
public void purchase() {
System.out.println("格力空调正在材料.");
}
}
/**
* @description: 格力生产
**/
public class GreeProduct implements IProduct {
@Override
public void make() {
System.out.println("格力正在生产空调.");
}
}
/**
* @description: 格力精加工
**/
public class GreeProcess implements IProcess {
@Override
public void processing() {
System.out.println("格力正在对空调进行精加工.");
}
}
/**
* 格力抽象工厂实现工具类
*/
public class GreeAbstractAirConditioner implements AbstractFactory {
@Override
public IPurchase getPurchase() {
return new GreePurchase();
}
@Override
public IProduct makeProduct() {
return new GreeProduct();
}
@Override
public IProcess processing() {
return new GreeProcess();
}
}
单元测试
@Test
public void test(){
// 创建一个格力工厂
AbstractFactory factory = new GreeAbstractAirConditioner();
IPurchase purchase = factory.getPurchase();
// 开始采购
purchase.purchase();
IProduct iProduct = factory.makeProduct();
// 开始生产
iProduct.make();
IProcess processing = factory.processing();
// 开始精加工
processing.processing();
}
4、单例模式
(一)、定义:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
(二)、结构:
单例模式分为两种:饿汉模式,懒汉模式。两者的区别主要在于私有对象的初始化时间不同,饿汉模式会在单例类加载时就被初始化,它主要是借助jvm类加载的机制来保证线程安全。而懒汉模式则是在调用getInstance()时,先进行验证,如果还没进行初始化,才会进行实例化。
(三)、代码演示
饿汉模式
/**
* @Description: 饿汉模式
*/
public class HuangrySingleton {
private static HuangrySingleton instance = new HuangrySingleton();
// 私有内部构造函数,不能被外部直接初始化
private HuangrySingleton(){}
// 全局唯一访问点
public static HuangrySingleton getInstance(){
return instance;
}
}
public class SingletonTest {
@Test
public void test() {
HuangrySingleton singleton = HuangrySingleton.getInstance();
HuangrySingleton singleton1 = HuangrySingleton.getInstance();
System.out.println(singleton);
System.out.println(singleton1);
}
}
懒汉模式
/**
* @Description: 懒汉模式
*/
public class LazySingleton {
// 防止指令重排
private volatile static LazySingleton instance;
private LazySingleton(){}
public static LazySingleton getInstance(){
if(instance==null) {
// 同步锁加双重验证,防止多线程场景下重复初始化
synchronized (LazySingleton.class){
if(instance==null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}
class LazySingletonTest {
public static void main(String[] args) {
new Thread(()->{
LazySingleton instance = LazySingleton.getInstance();
System.out.println(instance);
}).start();
new Thread(()->{
LazySingleton instance = LazySingleton.getInstance();
System.out.println(instance);
}).start();
}
}
单例还有一些其他的实现方式,比如静态内部类等,不做一一列举。