常用的设计模式

上一篇下一篇
Stream 深入,并行数据java并发编程

前言

设计模式是前辈们总结出来的最佳实践,经过世间沉淀,形成的一套解决问题的方案。通常一个设计模式专注于解决一类问题。
学习设计模式有助于提高代码质量(重用代码、易阅读、易维护、可靠性、扩展性等方面),也有助于提升程序员的设计能力。本篇介绍几个常用的设计模式。

1、单例模式

常常会遇到唯一的现象,比如一个班级里班主任只有一个。
简单定义如下:

public class ClassMaster {
  private String id;
  // 班主任名称
  private String name;
  private String gender;
}
public class Classes {

  public static void main(String[] args) {
    // 创建班主任实例
    ClassMaster classMaster = new ClassMaster();
    // 创建班主任实例2
    ClassMaster classMaster2 = new ClassMaster();
  }
}

可以看到这样的话一个 class 里面会可能存在不止一个班主任。
要解决这个问题,就是要让 ClassMaster 类只有一个实例。

即单例模式就是:
让某个类只有一个实例

实现步骤:

1.1、将构造函数设为私有

public class ClassMaster {
  private String id;
  // 班主任名称
  private String name;
  private String gender;

  private ClassMaster() {
  }
}

这样外部就无法创建实例

1.2、在类中定义一个静态实例

public class ClassMaster {
  private String id;
  // 班主任名称
  private String name;
  private String gender;
  private Static ClassMaster instance = new ClassMaster();
  
  private ClassMaster() {
  }
}

得保证有一个实例
因为静态属性是所有该类对象共有的,归属于整个类,所有这里可以理解为这个实例归属于这整个类,它并不能看成是某个对象的属性。
这就确保了一个类一个实例。

1.3、对外提供获取该静态实例的方法

因为这些属性都是私有的,所以得提供一个对外的接口来获取这个实例:

public class ClassMaster {
  private String id;
  // 班主任名称
  private String name;
  private String gender;
  private Static ClassMaster instance = new ClassMaster();
  
  private ClassMaster() {
  }

  public static ClassMaster getInstance(){
  	return instance;
  }
}

至此,就完成了一个单例模式的封装。

2、简单工厂模式

先做个总结:简单工厂模式就是将服务拆分,当多个场所需要同一个服务时,就可以将此服务抽象出来,单独由某个工厂承担
这样做的好处是,当这个服务需要改变时,原先是要在每个场所改动,现在只需要在工厂里改动即可。

实现步骤:

2.1、将同种产品类抽象出一个接口

java强调面向接口编程,就意味着工程应该生产一种产品,而不只是单个类的产品(这里的类指的是类和对象的类,一种产品里有多个类)。

比如水果:
水果接口:

public interface Fruit {
}

柠檬类:

public class Lemon implements Fruit {
}

西瓜类:

public class Watermelon implements Fruit {
}

榴莲类:

public class Durian implements Fruit {
}

2.2、将生产实例对象的过程收拢到工厂类中

public class FruitFactory {
    public static Fruit getFruit(Customer customer) {
        Fruit fruit = null;
        if ("sweet".equals(customer.getFlavor())) {
            fruit = new Watermelon();
        } else if ("acid".equals(customer.getFlavor())) {
            fruit = new Watermelon();
        } else if ("smelly".equals(customer.getFlavor())) {
            fruit = new Durian();
        }

        return fruit;
    }
}

2.3、加上抽象类

通常某种产品会有属性,而接口中一般只提供方法(接口里的属性都是静态常量),要给该种产品添加属性的话,可以再加上个抽象类,然后抽象类是接口的实现类,由抽象类派生出各个产品类,则产品类也就是接口的实现类,并且拥有属性。

还是上面的例子:
水果接口:

public interface Fruit {
	public String getName();
}

水果抽象类:

public abstract class AbstractFruit implements Fruit{
	private String name;
	public String getName(){
		return name;
	}
}

柠檬类:

public class Lemon implements Fruit {
}

西瓜类:

public class Watermelon implements Fruit {
}

榴莲类:

public class Durian implements Fruit {
}

这样一来,水果就都可以设置自己的name属性,并且提供了getName()接口。

3、抽象工厂模式

如果需要生产的不只是一种产品,而是多种产品、一系列,那简单工厂模式就有些吃力,或许你可以在简单工厂里多生产几种产品,但是这里有更优雅的解决方案:
抽象工厂:工厂的集合,工厂的工厂
实现步骤
以下图为例:
在这里插入图片描述

3.1、在简单工厂的基础上定义出工厂接口

public interface SnacksFactory {
    // 取得水果
    public Fruit getFruit(Customer customer);
    // 取得饮料
    public Drink getDrink(Customer customer);
}

其中水果工厂并不需要生产饮料,但它实现工厂接口后必须实现getDrink()方法,返回null即可

public class FruitFactory implements SnacksFactory {
    public Fruit getFruit(Customer customer) {
        Fruit fruit = null;
        if ("sweet".equals(customer.getFlavor())) {
            fruit = new Watermelon();
        } else if ("acid".equals(customer.getFlavor())) {
            fruit = new Lemon();
        } else if ("smelly".equals(customer.getFlavor())) {
            fruit = new Durian();
        }

        return fruit;
    }

    public Drink getDrink(Customer customer) {
        return null;
    }
}

3.2、将生产工厂实例对象的过程收拢到抽象工厂类中

public class SnacksFactoryBuilder {
    public SnacksFactory buildFactory(String choice) {
        if (choice.equalsIgnoreCase("fruit")) {
            return new FruitFactory();
        } else if (choice.equalsIgnoreCase("drink")) {
            return new DrinkFactory();
        }
        return null;
    }
}

3.3、也可加上抽象类

对于工厂,如果需要给工厂设置属性,也可定义一个工厂的抽象类,作为工厂接口的实现类;
对于产品,甚至可以定义一个AbstractSnake抽象类,是FoodDrink接口的实现类,派生出所有产品类。

上一篇下一篇
Stream 深入,并行数据java并发编程
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值