设计模式只是人们在长期实践中,利用语法规设计出来的模式,没有一成不变的模式,人们需要在长期的时间过程中,具体情况具体分析,不应该把设计模式当作信条。但是我个人人为熟练掌握集中常见的设计模式,在以后的阅读中还是有帮助的。
下面介绍自己看到的几种设计模式,我会结合阅读到的,网上搜索的,以及自己的理解 ,用白话描述,有说的不对的,请指教。
1 策略模式:定义一组 算法族,让这些算法族可以互相替换。下面的是类图,请参照图阅读文字。
context中有变量strategy 这个变量会在 最后的子类strategyA,strategyB,strategyC,中实现。你可以按照自己的需求,实例化这些策略族中的任意一种策略,并任意切换。
测试方法:
public static mian (String args[]){
Context con = new strategyA();
con.execute();
Context con1 = new strategyA();
con1.execute();
}
2观察者模式:主题会将自己变化的信息,主动传递给观察者们,观察者们可以主动注册自己到主题,或者将自己从主题中删除。但是他们相互并不知道对方具体的实现是什么。在JDK中有相应的实现观察者模式的应用java.util.observable(主题) and java.util.observer (观察者)
注:类图中的concreteObserver 中的属性Subject是有必要的,为了到时候反过来能找到他的主题是谁,方便删除自己。
3。装饰者模式:装饰着就是同一个物种的东西,然后加上点新的属性。请结合类图跟测试方法理解。还可以参考java.io
(由于装饰者模式由很多类装饰,所以通常会产生大量的可用类,不方便掌握。)
测试方法:
public static main(String args[]){
component com = new ConcreteComponent();
com = new ComcreteDecoratorA(com);
com = new ComcreteDecoratorB(com);
}
下面是类如:
4.工厂模式,这种模式很常见 下面介绍三种,简单工厂模式,工厂模式,抽象工厂模式。
4.1简单工厂:就是将实例化类的代码,抽离出来,很常见。结合下面的类图 工厂类 返回操作对象
测试方法:
COperation co = new COperation(1,2);
4.2工厂模式:把类实例化的过程延迟到子类中。工厂跟产品是平行的层级关系 具体的类图如下,ConcreteFactory里面实例化ConcreteProduct
测试方法
AbstructFactory af = new ConcreteFactory();
ConcreteProductA cp = af.getConcreteProductA();
4.3抽象工厂:通过接口创建相关的,依赖的对象家族,而不需要指定对象家族的具体类。(也就是说,抽象工厂创建出来很多对象,你不用挨个指定)
依赖倒置原则:要依赖抽象,不要以来具体类。
5.单例模式:(看head first之前我还真不知道这是个模式。)
5.1懒汉式单例
1、在getInstance方法上加同步
public static synchronized Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
2、双重检查锁定
5.2饿汉式单例
public class Singleton1 {
6命令模式:将命令行为还有接受命令的对象,封装起来,(说实话这部分没有看懂,不知道是不是我自己想简单了)
参照下面的类图,客户端,创建一个命令 Command com = new ConcreteCommand();并把这个命令交给Invoker(),Invoker把命令交给Receiver,Receiver执行命令的execute方法。
7.适配器模式与外观模式:
适配器模式:原本我们有一个A功能,客户需要这个A功能,但是却需要使用不同的调用方式来使用,这时候就需要一个适配器B,将A的功能封装,然后将调用方式换成客户可以接受的。如类图,客户要的是target,而我们目前只有Adaptee,(这里将Adaptee组合到Adapter里面)
外观模式:将复杂的调用方式组合成一个相对简单的调用方式,也就是定义了一个接口,来访问系统中的一群接口,使用了最少只是原则。
8.模板方法模式:将一组算法封装起来,只暴露部分可以业务需要的功能。jDK中的线程就是这种设计模式。
如图:父类含有咖啡因的饮料中有好多公共的方法,可以给茶叶和咖啡使用,其中我们不想被修改的方法,定义为final,需要下面的业务实现的定义为abstruct,还有一些钩子方法。所谓的钩子方法就是,一些已经被父类实现,但是子类也可以覆盖的方法,这些方法决定了代码的走向,如addComdments();
迭代模式,组合模式,状态模式没看。。
11.代理模式 代理模式有很多种
11.1远程代理模式,调用不在同一个jvm的方法
要使用JDK里面的java.rmi
1.一个interface 继承Remote
2.一个实现interface的实现类implA,继承UniCastRemoteObject,
3.开启RMI,rmiregister
4.生成客户端代理和服务器端代理 rmic + implA
5.执行方法
implA a = new implA();
Naming.rebind("implAName",a);
6.将步骤4生成的客户端代码,放到客户端,
7,在客户端执行
implA a = Naming.lookUp("rmi:127.0.0.1/implAName");
就可以获得对端代理
11.2虚拟代理,由于消耗资源可能过大,所以加一个代理;先将代理给客户,等客户真正需要真实对象,或者真是对象加载完了,在把真实对象给客户端。
11.3权限代理,权限代理基于动态代理 也是用到了JDK中的类Proxy还有InvocationHandler。
参照下面的类图:右下的InvocationHandler,继承了JDK中的InvocationHandler,同时组合了真实的对象RealSubject,
Proxy.newProxy(类加载起,类接口,实例化的类)产生代理,
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interfaceSubject {
public String say(String name,int age);
}
classRealSubject implementsSubject {
public String say(String name,int age) {
return"Hi "+name + ", You have been " + age+" years old." ;
}
}
classMyInvocationHandler implementsInvocationHandler {
@Override public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
for (int i = 0; i < args. length; i++) {
if (String.class.isInstance(args[i])) {
String temp = (String) args[i]; args[i]= temp.toUpperCase();
}
}
Subject realObj= new RealSubject();
Object temp = method.invoke(realObj, args);
return temp;
}
}
publicclassInvocationHandlerTest {public static void main(String[] args) {
Subject proxy = (Subject)Proxy.newProxyInstance( Subject.class.getClassLoader(),new Class[]{Subject.class}, new MyInvocationHandler() );
String info = proxy.say("tom",10); System. out.println(info);
}
}