Java中常见的设计模式
设计模式是软件设计中针对常见问题的可复用解决方案,它们提供了代码组织和架构的最佳实践,Java中常见的设计模式可分为创建型、结构型和行为型三类。下面就给大家介绍一些常用的设计模式和案例。
创建型模式:管理对象创建
1.单例模式
确保一个类只有一个实例,并且提供了一种访问其唯一对象的方式,不需要再实例化该类对象,可直接访问,避免重复消耗资源。
(1)懒汉式 public class Singleton {
/* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
private static Singleton instance = null;
/* 私有构造方法,防止被实例化 */
private Singleton() {
}
/* 1:懒汉式,静态工程方法,创建实例 */
public static Singleton getInstance() {
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
(2)饿汉式
public class Singleton {
/* 持有私有静态实例,防止被引用 */
private static Singleton instance = new Singleton();
/* 私有构造方法,防止被实例化 */
private Singleton() {
}
/* 1:懒汉式,静态工程方法,创建实例 */
public static Singleton getInstance() {
return instance;
}
}
使用场景:
- 需要定义大量静态常量和静态方法的环境
- 创建一个对象需要消耗的资源过多,比如io访问和数据库资源
2.工厂方法模式
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类
接口
public interface Fruit {
public void print();
}
2个实现类
public class Apple implements Fruit{
@Override
public void print() {
System.out.println("我是一个苹果");
}
}
public class Orange implements Fruit{
@Override
public void print() {
System.out.println("我是一个橘子");
}
}
工厂类
public class FruitFactory {
public Fruit produce(String type){
if(type.equals("apple")){
return new Apple();
}else if(type.equals("orange")){
return new Orange();
}else{
System.out.println("请输入正确的类型!");
return null;
}
}
}
使用场景:
- 框架开发中的扩展支持:在构建应用程序框架时,如果开发者希望允许使用者自定义某些组件的行为而不改变整体架构,则可以通过定义接口并让具体的实现由继承者提供。
-
处理不同类型的文件解析器:假设有一个应用需要读取多种格式的数据源(比如JSON、XML),每种数据源对应不同的解析逻辑。通过引入工厂方法模式可以让各个具体工厂负责实例化相应的解析工具,并返回给调用方统一的产品类型。
3.建造者模式
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
public class Build {
static class Student{
String name = null ;
int number = -1 ;
String sex = null ;
public Student(Builder builder) {
this.name=builder.name;
this.number=builder.number;
this.sex=builder.sex;
}
static class Builder{
String name = null ;
int number = -1 ;
String sex = null ;
public Builder setName(String name){
this.name=name;
return this;
}
public Builder setNumber(int number){
this.number=number;
return this;
}
public Builder setSex(String sex){
this.sex=sex;
return this;
}
public Student build(){
return new Student(this);
}
}
}
public static void main(String[] args) {
Student A=new Student.Builder().setName("张 三").setNumber(1).build();
Student B=new Student.Builder().setSex("男").setName("李四").build();
System.out.println(A.name+" "+A.number+" "+A.sex);
System.out.println(B.name+" "+B.number+" "+B.sex);
}
}
使用场景:相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式
结构型模式:对象组合的灵活性
1.适配器模式
将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
主要分为三种:
-
类适配:创建新类,继承源类,并实现新接口
-
对象适配:创建新类持源类的实例,并实现新接口
-
接口适配:创建新的抽象类实现旧接口方法
2.代理模式
为其他对象提供一种代理以控制对这个对象的访问
interface Source{ void method();}
class OldClass implements Source{
@Override
public void method() {
}
}
class Proxy implements Source{
private Source source = new OldClass();
void doSomething(){}
@Override
public void method() {
new Class1().Func1();
source.method();
new Class2().Func2();
doSomething();
}
}
3.装饰者模式
动态地给一个对象添加一些额外的职责。
interface Source{ void method();}
public class Decorator implements Source{
private Source source ;
public void decotate1(){
System.out.println("decorate");
}
@Override
public void method() {
decotate1();
source.method();
}
}
使用场景:扩展一个类的功能,或者增加附加功能;动态的给一个对象增加功能,还可以动态撤销
行为型模式:对象交互的智能化
1. 观察者模式
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
public abstract class Subject {
//定义一个观察者数组
private Vector obsVector = new Vector();
//增加一个观察者
public void addObserver(Observer o){
this.obsVector.add(o);
}
//删除一个观察者
public void delObserver(Observer o){
this.obsVector.remove(o);
}
//通知所有观察者
public void notifyObservers(){
for(Observer o:this.obsVector){
o.update();
}
}
}
使用场景:关联行为场景;事件多级触发场景
2.策略模式
定义一组算法,将每个算法都封装起来,并且使它们之间可以互换
// 会员卡接口
public interface VipCard {
public void discount();
}
public class GoldCard implements VipCard {
@Override
public void discount() {
System.out.println("金卡打7折");
}
}
public class SilverCard implements VipCard {
@Override
public void discount() {
System.out.println("银卡打8折");
}
}
public class CopperCard implements VipCard {
@Override
public void discount() {
System.out.println("铜卡打9折");
}
}
public class Normal implements VipCard {
@Override
public void discount() {
System.out.println("普通会员没有折扣");
}
}
// 会员卡容器类
public class VipCardFactory {
private static Map<String, VipCard> map = new ConcurrentHashMap<>();
static {
map.put("gold", new GoldCard());
map.put("silver", new SilverCard());
map.put("copper", new CopperCard());
}
public static VipCard getVIPCard(String level) {
return map.get(level) != null ? map.get(level) : new Normal();
}
}
// 测试方法
public static void main(String[] args) {
//金卡打7折
VipCardFactory.getVIPCard("gold").discount();
//银卡打8折
VipCardFactory.getVIPCard("silver").discount();
//普通会员没有折扣
VipCardFactory.getVIPCard("other").discount();
}
使用场景:算法需要自由切换的场景;多个类只有在算法或行为上有不同的场景
3.责任链模式
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
public abstract class Handler {
private Handler nextHandler;
//每个处理者都必须对请求做出处理
public final Response handleMessage(Request request){
Response response = null;
//判断是否是自己的处理级别
if(this.getHandlerLevel().equals(request.getRequestLevel())){
response = this.echo(request);
}else{ //不属于自己的处理级别
//判断是否有下一个处理者
if(this.nextHandler != null){
response = this.nextHandler.handleMessage(request);
}else{
//没有适当的处理者,业务自行处理
}
}
return response;
}
//设置下一个处理者是谁
public void setNext(Handler _handler){
this.nextHandler = _handler;
}
//每个处理者都有一个处理级别
protected abstract Level getHandlerLevel();
//每个处理者都必须实现处理任务
protected abstract Response echo(Request request);
}
使用场景:多个对象可以处理同一请求,但具体由哪个对象处理则在运行时动态决定;在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;可动态指定一组对象处理请求。