java中设计模式
提示:该文章为《java面试系列》
一、模式分类
“设计模式”一书讨论了23种不同的模式,分为以下三种类别(所有这些模式都围绕着可能变化的特定方面)。
创建型:如何创建对象。 这通常涉及隔离对象创建的细节,这样你的代码就不依赖于具体的对象的类型,因此在添加新类型的对象时不会更改。单例模式(Singleton)被归类为创作模式,本章稍后你将看到Factory Method的示例。
构造型:设计对象以满足特定的项目约束。它们处理对象与其他对象连接的方式,以确保系统中的更改不需要更改这些连接。
行为型:处理程序中特定类型的操作的对象。这些封装要执行的过程,例如解释语言、实现请求、遍历序列(如在迭代器中)或实现算法。本章包含观察者和访问者模式的例子。
二、面向实现
代理模式和桥接模式。
在结构上,代理模式和桥接模式的区别很简单:代理模式只有一个实现,而桥接模式有多个实现。在设计模式中被认为是不同的:代理模式用于控制对其实现的访问,而桥接模式允许您动态更改实现。但是,如果您扩展了“控制对实现的访问”的概念,那么这两者就可以完美地结合在一起。
1. 单例模式
(1)是一种提供一个且只有一个对象实例的方法。这在java库中使用,但是这有个更直接的示例。
(2)确保一个类只有一个实例,并提供该实例的全局访问点。
代码如下所示(线程安全):
package www.gzhou.Single;
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton(){
//私有预防创建多个实例
}
public static Singleton getOneInstance(){
if(oneInstance == null){
oneInstance = new Singleton();
}
return oneInstance;
}
}
(3)也可以采用延迟加载(线程安全)
public static synchronized Singleton getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
(4)也可以多次检验(线程安全)
当没有被实例化的时候再加锁
package www.gzhou.Single;
public class Singleton1 {
//防止指令重排序
private volatile static Singleton1 oneInstance;
private Singleton1(){
}
public static Singleton1 getOneInstance(){
if(oneInstance == null){ //多重判断,
synchronized (Singleton1.class){
if(oneInstance == null){ //多重判断
oneInstance = new Singleton1();
}
}
}
return oneInstance;
}
}
(5)静态内部类实现(线程安全)
package www.gzhou.Single;
public class Singleton2 {
private Singleton2(){
}
private static class SingletonHolder{
private static final Singleton2 instance = new Singleton2();
}
public static Singleton2 getoneInstance(){
return SingletonHolder.instance;
}
}
当Singleton2加载的时候,它的内部类 SingletonHolder还没在加载到内存。只有当调用SingletonHolder.instance的时候才会被加载初始化实例,而且只只加载一次。
(6)枚举实现
public enum Singleton {
INSTANCE;
private String objName;
public String getObjName() {
return objName;
}
public void setObjName(String objName) {
this.objName = objName;
}
}
防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止多次实例化的代码。该实现是由 JVM 保证只会实例化一次,因此不会出现上述的反射攻击。
2. 代理模式
具体实现不需要与代理对象具有相同的接口;只要代理对象以某种方式“代表具体实现的方法调用,那么基本思想就算实现了。然而,拥有一个公共接口是很方便的,因此具体实现必须实现代理对象调用的所有方法。
interface ProxyBase {
void f();
void g();
void h();
}
class Proxy implements ProxyBase {
private ProxyBase implementation;
Proxy() {
implementation = new Implementation();
}
// Pass method calls to the implementation:
@Override
public void f() {
implementation.f();
}
@Override
public void g() {
implementation.g();
}
@Override
public void h() {
implementation.h();
}
}
class Implementation implements ProxyBase {
public void f() {
System.out.println("Implementation.f()");
}
public void g() {
System.out.println("Implementation.g()");
}
public void h() {
System.out.println("Implementation.h()");
}
}
public class ProxyDemo {
public static void main(String[] args) {
Proxy p = new Proxy();
p.f();
p.g();
p.h();
}
}

3.状态模式
状态模式向代理对象添加了更多的实现,以及在代理对象的生命周期内从一个实现切换到另一种实现的方法:
interface StateBase {
void f();
void g();
void h();
void changeImp(StateBase newImp);
}
class State implements StateBase {
private StateBase implementation;
State(StateBase imp) {
implementation = imp;
}
@Override
public void changeImp(StateBase newImp) {
implementation = newImp;
}
// Pass method calls to the implementation:
@Override
public void f() {
implementation.f();
}
@Override
public void g() {
implementation.g();
}
@Override
public void h() {
implementation.h();
}
}
class Implementation1 implements StateBase {
@Override
public void f() {
System.out.println("Implementation1.f()");
}
@Override
public void g() {
System.out.println("Implementation1.g()");
}
@Override
public void h() {
System.out.println("Implementation1.h()");
}
@Override
public void changeImp(StateBase newImp) {
}
}
class Implementation2 implements StateBase {
@Override
public void f() {
System.out.println("Implementation2.f()");
}
@Override
public void g() {
System.out.println("Implementation2.g()");
}
@Override
public void h() {
System.out.println("Implementation2.h()");
}
@Override
public void changeImp(StateBase newImp) {
}
}
public class StateDemo {
static void test(StateBase b) {
b.f();
b.g();
b.h();
}
public static void main(String[] args) {
StateBase b =
new State(new Implementation1());
test(b);
b.changeImp(new Implementation2());
test(b);
}
}

在main()中,首先使用第一个实现,然后改变成第二个实现。代理模式和状态模式的区别在于它们解决的问题。设计模式中描述的代理模式的常见用途如下:
远程代理。它在不同的地址空间中代理对象。远程方法调用(RMI)编译器rmic会自动为您创建一个远程代理。
虚拟代理。这提供了“懒加载”来根据需要创建“昂贵”的对象。
保护代理。当您希望对代理对象有权限访问控制时使用。
智能引用。要在被代理的对象被访问时添加其他操作。例如,跟踪特定对象的引用数量,来实现写时复制用法,和防止对象别名。一个更简单的例子是跟踪特定方法的调用数量。您可以将Java引用视为一种保护代理,因为它控制在堆上实例对象的访问(例如,确保不使用空引用)。
4、状态机
桥接模式允许程序员更改实现,状态机利用一个结构来自动地将实现更改到下一个。当前实现表示系统所处的状态,系统在不同状态下的行为不同(因为它使用桥接模式)。基本上,这是一个利用对象的“状态机”。将系统从一种状态移动到另一种状态的代码通常是模板方法模式。
工厂模式
其实这里面很多很多,下一篇(以后)继续更新…
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)