JAVA常见的设计模式

     已经悄然声息的把数据库的一些基础的东西已经过了一遍,接下来就是需要把我的核心JAVA基础性的东西先整理出来了,但是在这之前我想简单介绍以下我们平常在JAVA开发中遇到到常见的设计模式。两天的时间,整理出来10种常见的设计模式,但是好像很陌生,于是我自己在某宝上下了一单,买了一本JAVA设计模式的书,决定把这块东西给啃下来。

                      什么是设计模式?

                      设计模式是一套被反复利用的。多数人知晓的,经过分类编程得到的设计经验的总结,使用设计模式是为了可重用代码,让代码更容易让人理解,保证代码的可靠性。

                       单例模式(保证一个类仅有一个实例,并且提供一个全局访问点)

                       根据实现的方式不同,我们可以分为饿汉式,懒汉式,内部静态类,双重校验锁,以及枚举单例

                       特点:某个类只能有一个实例。它必须自行创建这个实例,他必须自行向整个系统提供这个实例。

                        应用:网站计数器,垃圾回收站,操作系统的文件系统,数据库连接池,读取配置文件的类等

                        eg:    饿汉模式

Class SingleDemo{
private static SingleDemo singleDemo = new SingleDome()
private SingleDemo(){}
public static SingleDemo geySingleDemo{
return singleDemo;
}
}
                             
代码(懒汉模式)
Class SingleDemo{
private static SingleDemo singleDemo = null;
public Single(){
if ( singleDemo == null )
singlDemo=new SingleDemo()
return singleDemo;
}
}
加锁/线程安全
Class SingleDemo{
private static SingleDemo singleDemo = null;
public SingleDemo(){}
//同步函数的demo
public static synchronized SingleDemo GetSingleDemo(){
if( singleDemo == null)
singleDemo=new SingleDemo();
return singleDemo;
}
//同步代码块的demo加锁,安全高效
public static SingleDemo getSingleDemo(){
if( singleDemo == null)
synchronized(SingleDemo.class){
if (singleDemo == null)
singleDome=new SingleDemo()
}
return singleDemo;
}

}

枚举单例:注意构造方法私有
eg:enum Single { Single; private Single() { }

②代理模式:是一种设计模式,提供了对目标得另外得访问方式,即通过代理对象访问目标对象,可以在目标对象实现得基础上,增加额外得功能操作,即扩展目标对象得功能。
静态代理:需要定义借口或者父类,被代理的对象和代理对象一起实现相同的接口或者继承相同的父类。
动态代理有以下特点:
代理对象,不需要实现接口
代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象的接口类型)
动态代理也叫做:JDK代理,接口代理
eg:
/** * 创建动态代理对象 * 动态代理不需要实现接口,但是需要指定接口类型 */public class ProxyFactory{ //维护一个目标对象 private Object target; public ProxyFactory(Object target){ this.target=target; } //给目标对象生成代理对象 public Object getProxyInstance(){ return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开始事务2"); //执行目标对象方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务2"); return returnValue; } } ); }}



/** * 测试类 */public class App { public static void main(String[] args) { // 目标对象 IUserDao target = new UserDao(); // 【原始的类型 class cn.itcast.b_dynamic.UserDao】 System.out.println(target.getClass()); // 给目标对象,创建代理对象 IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance(); // class $Proxy0 内存中动态生成的代理对象 System.out.println(proxy.getClass()); // 执行方法 【代理对象】 proxy.save(); }}


注意:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。
还有一种是子类代理(Cglib代理)

public class ProxyFactory implements MethodInterceptor{ //维护目标对象 private Object target; public ProxyFactory(Object target) { this.target = target; } //给目标对象创建一个代理对象 public Object getProxyInstance(){ //1.工具类 Enhancer en = new Enhancer(); //2.设置父类 en.setSuperclass(target.getClass()); //3.设置回调函数 en.setCallback(this); //4.创建子类(代理对象) return en.create(); } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { System.out.println("开始事务..."); //执行目标对象的方法 Object returnValue = method.invoke(target, args); System.out.println("提交事务..."); return returnValue; }}
/** * 测试类 */public class App { @Test public void test(){ //目标对象 UserDao target = new UserDao(); //代理对象 UserDao proxy = (UserDao)new ProxyFactory(target).getProxyInstance(); //执行代理对象的方法 proxy.save(); }}
③策略设计模式,创建一个能够根据所传递对象不同而具有不同行为的方法称为策略设计模式。
eg:
/* 基类,这里可以是普通类,也可以是一个接口 */abstract class Shape{ public abstract void outputShape();}/* 策略 */class Circle extends Shape{ public void outputShape(){ System.out.println("this is a circle"); }}/* 策略 */class Square extends Shape{ public void outputShape(){ System.out.println("this is a square"); }}/* 策略 */ class Triangle extends Shape{ public void outputShape(){ System.out.println("this is a triangle"); }}public class Strategy { /* Strategy.strategic()方法接收一个Shape类型的引用作为参数 * 这个引用可以是任何类型的Shape,如Circle、Square、Triangle * 根据所传递参数的不同,strategic方法有不同的行为略 * */ public static void strategic(Shape S){ // 接收策略引用的方法,S是策略引用 S.outputShape(); // 方法中固有不变的部分 } public static void main(String[] args){ strategic(new Circle()); // 新建Circle()对象作为strategic()方法的参数,这里的circle()对象就是一个策略,这里用到了向上转型 strategic(new Square()); // 策略Square()对象 strategic(new Triangle()); // 策略Triangle()对象 }}/* * output: * this is a circle * this is a square * this is a triangle * */
④适配器模式:我们需要一个类A来实现B,但是类A并没有实现B种的所有方法,而类A是不能被改变的,这时我们可以创建一个类Cbong实现接口B,这个类C就是一个适配器。适配器中的代码将接受你所拥有的接口,并产生你需要的接口。适配器模式分为类适配器模式和对象适配器模式。
对象适配器模式:
package com.tongye.adapters;public interface TargetInterface { void method1(); void method2();}/*****************************/package com.tongye.adapters;/* 源类,我们需要这个类实现接口 TargetInterface,但这个类不能被改变 * 源类与接口之间是没有关系的 * */class BeAdapted{ public void method1(){ System.out.println("method1"); }}/* 这是适配器,它接受了中已有的接口并产生我们需要的接口 */class Adapter implements TargetInterface{ private static BeAdapted adapted; // 声明一个BeAdapted对象引用 public Adapter(BeAdapted adapted){     // 构造方法,接收一个BeAdapted引用作为参数 this.adapted = adapted; } public void method1(){ // method1()在源类BeAdapted中有,这里直接委派 this.adapted.method1(); } public void method2(){ // method2()方法无法通过继承获得,需要自己声明 System.out.println("method2"); }}
类适配器模式:
public interface TargetInterface { void method1(); void method2();}/*****************************/package com.tongye.adapters;/* 源类,我们需要这个类实现接口 TargetInterface,但这个类不能被改变 * 源类与接口之间是没有关系的 * */class BeAdapted{ public void method1(){ System.out.println("method1"); }}/* 这是适配器,它接受了BeAdapted中已有的接口并产生我们需要的接口 * method1()方法继承自BeAdapted类(即已有的接口),不用再作声明 * 这里适配器的作用相当于为源类与接口之间建立了一种关系,类似于 implements * */class Adapter extends BeAdapted implements TargetInterface{ public void method2(){ // method2()方法无法通过继承获得,因而需要自己声明,这就是适配器为我们产生的接口 System.out.println("method2"); }}public class ClassAdapter { public static void main(String[] args){ Adapter adapt = new Adapter(); adapt.method1(); adapt.method2(); }}
注意:适配器与源类继承关系则为类适配器模式,适配器与源类为委托关系,则为对象适配器模式。

⑤装饰者模式:当一样事物的本身是有一些主体和一个装饰者存在,则可以使用装饰者模型。动态给类加功能。
eg:





缺点:就是产生太多的装饰者的小类,有类爆炸的趋势。
⑥外观模式:简称门面模式,为系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易。
⑦命令模式:将一个请求封装成一个对象,从而使你不同的请求对客户进行参数化。
在这个命令模式下有三种角色:
Receiver 接受者角色:该角色就是干活的角色,命令传递到这里使应该被执行的
Command 命令角色:需要执行的命令的角色都在这里申明
Invoker 调用者角色:接受到命令,并执行命令

eg://通用Receiver类public abstract class Receiver { public abstract void doSomething();}//具体Receiver类public class ConcreteReciver1 extends Receiver{ //每个接收者都必须处理一定的业务逻辑 public void doSomething(){ } } public class ConcreteReciver2 extends Receiver{ //每个接收者都必须处理一定的业务逻辑 public void doSomething(){ } }//抽象Command类public abstract class Command { public abstract void execute();}//具体的Command类public class ConcreteCommand1 extends Command { //对哪个Receiver类进行命令处理 private Receiver receiver; //构造函数传递接收者 public ConcreteCommand1(Receiver _receiver){ this.receiver = _receiver; } //必须实现一个命令 public void execute() { //业务处理 this.receiver.doSomething(); } } public class ConcreteCommand2 extends Command { //哪个Receiver类进行命令处理 private Receiver receiver; //构造函数传递接收者 public ConcreteCommand2(Receiver _receiver){ this.receiver = _receiver; } //必须实现一个命令 public void execute() { //业务处理 this.receiver.doSomething(); } }//调用者Invoker类public class Invoker { private Command command; public void setCommand(Command _command){ this.command = _command; } public void action() { this.command.execute(); }}//场景类public class Client { public static void main(String[] args){ Invoker invoker = new Invoker(); Receiver receiver = new ConcreteReceiver1(); Command command = new ConcreteCommand1(receiver); invoker.setCommand(command); invoker.action(); }}

优点:
类间解耦:调用者与接受者之间没有任何的依赖关系,调用者只需要调用抽象类的execute方法就行了。不需要了解到底哪个使接收者执行。
可扩展性:Command的子类可以非常容易的扩展,而调用者Invoker个高层次的模块不产生严重的代码耦合。
命令模式可以结合责任链模式,实现命令族解析任务;结合模板方法模式,则可以减少 Command子类的膨胀问题
⑧创建者模式
创建者模式又叫建造者模式,是将一个复杂的对象构建与它表示分离,使得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程,加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象。

在创建者模式中包括以下四种角色
建造者角色 对复杂对象创建过程加以抽象,给出一个抽象的接口,以规范产品对象的各个组成部分的建造,这个接口规定要实现复杂对象的哪个部分创建,但并不涉及具体对象不见的创建。
具体创建者角色 实现上述接口,针对不同的业务逻辑,具体复杂对象的各个部分的创建。在建造完成后,提供产品的实例。
指导者 调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整的创建或者按某种顺序创建。
产品 要创建的复杂对象, 一般来说包含多个部分。
产品
public class Product {
private List<String> parts = new ArrayList<String>();

public void add(String partName){
parts.add(partName);
}

public void show(){
System.out.println("----产品创建----");
for (String part : parts) {
System.out.println(part);
}
}
}
建造者角色
public abstract class Builder {
protected abstract void buildPartA();
protected abstract void buildPartB();
protected abstract void buildPartC();

protected abstract Product getResult();
}
具体建造者
public class BuilderA extends Builder {
private Product product = new Product();

@Override
protected void buildPartA() {
product.add("partA");
}

@Override
protected void buildPartB() {
product.add("partB");
}

@Override
protected void buildPartC() {
product.add("partC");
}

@Override
protected Product getResult() {
return product;
}
}

public class BuilderB extends Builder {
private Product product = new Product();

@Override
protected void buildPartA() {
product.add("partX");
}

@Override
protected void buildPartB() {
product.add("partY");
}

@Override
protected void buildPartC() {
product.add("partZ");
}

@Override
protected Product getResult() {
return product;
}
}
指导者:
public class BuilderDirector {

private Builder builder = null;

public BuilderDirector(Builder builder){
this.builder = builder;
}

public Product build(){
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}

}


Test测试


public class BuilderTest {

public static void main(String[] args) {

BuilderDirector director = new BuilderDirector(new BuilderB());
Product product = director.build();
product.show();
}

}

⑨抽象工厂模式:提供一个创建一系列相关或者依赖对象的接口,而无需指定他们具体的类。
封装性 每个产品的实现类不是高层模块要关心的,他要关心的是什么。是接口,是抽象,它不关心对象是如何创建出来的这个由谁负责,主要知道工厂类是谁,我们就能创建出一个需要对象,省时省力,优秀的设计就该如此。
⑩ 观察者模式,有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者同时监听一个主题对象。这个对象在状态发生改变时,会通知所有观察者对象,使他们能够自动更新自己。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值