1.单例设计模式singleton——只能产生一个实例化对象的设计模式
(为什么不用静态变量代替呢?因为静态变量在程序一开始就创建了对象,可能会比较消耗资源)
public class Singleton {
private static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if(uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
public class singletonTest {
public static void main(String args[]){
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println("s1:" + s1 + ",s2:" + s2);
}
}
运行结果显示:
s1:designPattern.Singleton@6f94fa3e,s2:designPattern.Singleton@6f94fa3e
两个对象的地址相同,表示只产生了一个实例化对象
2.工厂设计模式Factory—将对象的创建封装起来
(1)简单工厂:程序中只有一个工厂,在工厂内部根据数据逻辑判断来创建不同对象
实例:假设有一个Sender接口,以及实现了这两个接口的类:MailSender和SmsSender
public interface Sender{
public void Send();
}
public class MailSender implements Sender{
public void Send(){
System.out.println("mailsender!");
}
}
public class SmsSender implements Sender{
public void Send(){
System.out.println("smssender!");
}
}
现在设计一个简单工厂对象用于产生这两个类的实例化对象如下:
public class SendFactory{
public Sender produce(String type){
if("mail".equals(type)){
return new MailSender();
}else if("sms".equals(type)){
return new SmsSender();
}else{
return null;
}
}
}
调用过程:
SendFactory sendproduct = new SendFactory();
Sender send = sendproduct.produce("mail");
整个代码中只有一个工厂类,这就是简单工厂。
(2)工厂方法:针对于简单工厂的改进(由于传送数据出错导致返回null),对于每一种类设置一个工厂方法用于返回相应的对象。
工厂方法代码如下:
public class SendfunctionFactory{
public Sender produceMail(){
return new MailSender();
}
public Sender produceSms(){
return new SmsSender();
}
}
调用过程:
SendfunctionFactory factory = new SendfunctionFactory();
Sender send = factory.produceMail();
大部分情况下,都会对上述方法进行改进,即将上述工厂方法设置为静态的,这样,不实例化工厂对象也可以调用相应的工厂方法。
(3)抽象工厂:针对于工厂方法中的不足—当添加了一个子类时,需要在已有的工厂中添加一个方法,改变了已有的代码。改进:写一个工厂接口,每一个类都有一个相应的工厂实现该接口,当添加一个类的时候,只需要添加一个工厂类就行,不必修改已有的工厂类。
代码如下:
public interface provider{
public Sender produce();
}
public class SendMailFactory implements provider{
public Sender produce(){
return new MailSender();
}
}
public class SendSmsFactory implements provider{
public Sender produce(){
return new SmsSender();
}
}
调用方式如下:
provider pro = new SendMailFactory();
Sender sender = pro.produce();
调用时指明是哪个工厂。
3.适配器设计模式adapter—将一个种类型转换成另外一种适合场景的类型
(1)类的适配器模式:希望将一个类转换成满足另一个接口的新类。
创建一个新类,继承原有的类,实现新的接口
实例:假设有一个源类Source和一个目标接口Targetable
public class Source{
public void method1(){
System.out.println("source's method1");
}
}
public interface Targetable{
public void method1();
public void method2();
}
现在想要通过适配器使source类可以实现目标接口,方式是,编写一个新类:
public class Adaptor extends Source implements Targetable{
public void method2(){
System.out.println("Adaptor's method2");
}
}
调用的方式:
Targetable target = new Adaptor();
target.method1();
target.method2();
(2)对象的适配器模式:希望将一个对象转换成一个新接口的对象
实现方式是,创建一个新类,该类包含一个原对象的属性,并且该类实现了接口中的方法。
public class Newclass implements Targetable{
private Source source;
public Newclass(Source source){
super();
this.source = source;
}
public void method1(){
System.out.println("newclass's method1");
}
public void method2(){
System.out.println("newclass's method2");
}
}
使用方式,使用给定的对象构造适配器类:
Source source = new Source();
Targetable target = new Newclass(source);
target.method1();
target.method2();
比如有一个接口有两个方法:
public interface Sourceable{
public void method1();
public void method2();
}
现在想产生两个类,类1只想要方法1,类2只想要方法2,实现方式是先构建一个抽象类:
public abstract class newclass implements Sourceable{
public void method1(){}
public void method2(){}
}
然后再让两个类继承该抽象类:
public class SourceSub1 extends newclass{
public void method1(){
System.out.println("sourcesub1's method1");
}
}
public class SourceSub2 extends newclass{
public void method2(){
System.out.println("sourcesub2's method2");
}
}
由于继承时可以不必重写所有方法,所以两个子类只需要重写自己想用的方法即可,使用方式:
Sourceable source1 = new SourceSub1();
Sourceable source2 = new SourceSub2();
source1.method1();
source1.method2();
source2.method1();
source2.method2();
4.装饰设计模式—给类添加新的功能
(为什么不用继承?因为继承时静态的,装饰设计模式可以动态的添加功能,避免了继承体系的臃肿)
对于一个类和一个接口,编写一个装饰类实现该接口,装饰类中含有源类的实例化对象。
如下,假设有一个接口SourceAble,和一个实现了该接口的类SourceClass:
public interface SourceAble{
public void method();
}
public class SourceClass implements SourceAble{
public void method(){
System.out.println("source method");
}
}
现在想丰富该类中method方法的功能,实现方式是编写一个装饰类:
public class DecoratorClass implements SourceAble{
private SourceAble source;
public DecoratorClass(SourceAble source){
super();
this.source = source;
}
public void method(){
System.out.println("before decorator");
source.method();
System.out.println("after decorator");
}
}
使用方式:
SourceAble source = new SourceClass();
SourceAble dec = new DecoratorClass(source);
dec.method();
(5) 代理设计模式proxy— 设计一个对象,该对象为另一个对象提供替身以控制该对象的访问,处理代理对象就像处理原始对象一样。(被代理的对象可以是远程对象、创建开销大的对象或者需要安全控制的对象)
代理模式和装饰模式的区别:
代理模式注重控制,原始的功能不变;
装饰模式注重功能的添加;
(个人觉得,在代码结构上没什么区别,主要区别是你这段代码的目的性)
动态代理模式— 一个代理类可以代理所有需要被代理接口(功能相似的接口)的子类对象
①JDK动态代理:代理的类实现了某一接口
用到了InvocationHandler接口
public interface InvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;
}
说明:
Object proxy:指被代理的对象。
Method method:要调用的方法
Object[] args:方法调用时所需要的参数
用到了Proxy类:
Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
参数说明:
ClassLoader loader:类加载器
Class<?>[] interfaces:得到全部的接口
InvocationHandler h:得到InvocationHandler接口的子类实例
实例代码如下:
interface BookFacade{
public void addBook();
}
class BookFacadeImpl implements BookFacade{
public void addBook(){
System.out.println("add book");
}
}
class BookFacadeProxy implements InvocationHandler{ //代理类实现InvocationHandler接口
private Object target;
public Object bind(Object target){ //执行对象的绑定
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader() ,target.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{ //实现接口里面的invoke方法
Object result = null;
System.out.println("begin");
result = method.invoke(target,args);
System.out.println("end");
return result;
}
}
public class JDKProxy {
public static void main(String args[]){
BookFacadeProxy proxy = new BookFacadeProxy();
BookFacade bookProxy = (BookFacade)proxy.bind(new BookFacadeImpl());
bookProxy.addBook();
}
}
②CGLIB动态代理:代理的类没有实现接口
public class BookFacadeCglib implements MethodInterceptor {
private Object target;
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
System.out.println("事物开始");
proxy.invokeSuper(obj, args);
System.out.println("事物结束");
return null;
}
}
(6)观察者模式observer—当一个对象变化的时候,跟其相关联的对象中的相应值也会变化
需要有两个接口:Subjec(被观察的对象接口),Observer(观察者的接口):
public interface Observer{
public void update();
}
public interface Subject{
public void add(Observer observer);//用于增加观察者
public void del(Observer observer);//用于删除观察者
public void notifyObservers();//用于通知所有观察者
public void operation();
}
定义一个抽象类实现被观察者接口:
public abstract class AbstractSubject implements Subject{
private List<myObserver> list = new ArrayList<myObserver>();
public void add(myObserver observer){
list.add(observer);
}
public void del(myObserver observer){
list.remove(observer);
}
public void notifyObservers(){
for(myObserver observer : list){
observer.update();
}
}
}
定义两个观察者类以及一个被观察者类:
public class Observer1 implements myObserver{
public void update(){
System.out.println("Observer1's update");
}
}
public class Observer2 implements myObserver{
public void update(){
System.out.println("Observer2's update");
}
}
public class mySubject extends AbstractSubject{
public void operation(){
System.out.println("my operation");
notifyObservers();
}
}
使用方法:
Subject sub = new mySubject();
sub.add(new Observer1());
sub.add(new Observer2());
sub.operation();