23种设计模式 慢慢来 自我理解

本文深入解析了工厂方法、抽象工厂、单例等十种经典设计模式,并提供了详细的代码示例,帮助读者理解每种模式的应用场景及其优势。

http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html


一、工厂方法模式(大多数建议第三种)

1、普通工厂模式: 就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建

  1. public class SendFactory {  
  2.   
  3.     public Sender produce(String type) {  
  4.         if ("mail".equals(type)) {  
  5.             return new MailSender();  
  6.         } else if ("sms".equals(type)) {  
  7.             return new SmsSender();  
  8.         } else {  
  9.             System.out.println("请输入正确的类型!");  
  10.             return null;  
  11.         }  
  12.     }  

2、多个工厂方法模式:普通工厂模式的改进, 普通工厂方法中如果传递字符串出错,则不能正确的创建对象; 工厂方法模式是提供多个工厂方法,分别创建对象

          public class SendFactory {  

                public Sender produceMail(){  
  1.         return new MailSender();  
  2.     }  
  3.       
  4.     public Sender produceSms(){  
  5.         return new SmsSender();  
  6.     }  

3、静态工厂方法 模式:将上面的多个工厂模式里的方法置为静态的,不需要创建实例,直接调用即可

  1. public class SendFactory {  
  2.       
  3.     public static Sender produceMail(){  
  4.         return new MailSender();  
  5.     }  
  6.       
  7.     public static Sender produceSms(){  
  8.         return new SmsSender();  
  9.     }  
  10. }
二、抽象工厂模式:(避免了像工厂方法模式,如果拓展就要改工厂类) 这个就是分两步, 1 定义一个 造工厂的对象接口 ,让类实现    

                                                                                                                                                                   2 再定义造出对象干什么事情的接口,让类实现

  1. public class Test {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Provider provider = new SendMailFactory();   //对象工厂
  5.         Sender sender = provider.produce();              //工厂造出对象
  6.         sender.Send();                                                    //对象干对应的事情
  7.     }  


三、单例模式: 目的是保证在 JVM中 保证该对象只有一个实例存在   这样可以节省资源, 减轻GC压力  (紧介绍  我认为最优的模式)

  1. public class SingletonTest {  
  2.   
  3.     private static SingletonTest instance = null;  
  4.   
  5.     private SingletonTest() {  
  6.     }  
  7.   
  8.     private static synchronized void syncInit() {  
  9.         if (instance == null) {  
  10.             instance = new SingletonTest();  
  11.         }  
  12.     }  
  13.   
  14.     public static SingletonTest getInstance() {  
  15.         if (instance == null) {  
  16.             syncInit();  
  17.         }  
  18.         return instance;  
  19.     }  

四、 建造者模式:  工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属   

                                   性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来得到的

  1. public class Builder {  
  2.       
  3.     private List<Sender> list = new ArrayList<Sender>();  
  4.       
  5.     public void produceMailSender(int count){  
  6.         for(int i=0; i<count; i++){  
  7.             list.add(new MailSender());  
  8.         }  
  9.     }  
  10.       
  11.     public void produceSmsSender(int count){  
  12.         for(int i=0; i<count; i++){  
  13.             list.add(new SmsSender());  
  14.         }  
  15.     }  

  16. 测试类:

    1. public class Test {  
    2.   
    3.     public static void main(String[] args) {  
    4.         Builder builder = new Builder();  
    5.         builder.produceMailSender(10);  
    6.     }  

五、原型模式:该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。本小结会通过对象的复制,进行讲解。在Java中,复制对象是

                           通过clone()实现的,先创建一个原型类

很简单,一个原型类,只需要实现Cloneable接口,覆写clone方法,此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口,你可以任意定义实现类的方法名,如cloneA或者cloneB,因为此处的重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,而在Object类中,clone()是native的

浅复制:将一个对象复制后,基本数据类型的变量都会重新创建,而引用类型,指向的还是原对象所指向的。

深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的。简单来说,就是深复制进行了完全彻底的复制,而浅复制不彻底


此处,写一个深浅复制的例子:

  1. public class Prototype implements Cloneable, Serializable {  
  2.   
  3.     private static final long serialVersionUID = 1L;  
  4.     private String string;  
  5.   
  6.     private SerializableObject obj;  
  7.   
  8.     /* 浅复制 */  
  9.     public Object clone() throws CloneNotSupportedException {  
  10.         Prototype proto = (Prototype) super.clone();  
  11.         return proto;  
  12.     }  
  13.   
  14.     /* 深复制 */  
  15.     public Object deepClone() throws IOException, ClassNotFoundException {  
  16.   
  17.         /* 写入当前对象的二进制流 */  
  18.         ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  19.         ObjectOutputStream oos = new ObjectOutputStream(bos);  
  20.         oos.writeObject(this);  
  21.   
  22.         /* 读出二进制流产生的新对象 */  
  23.         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  
  24.         ObjectInputStream ois = new ObjectInputStream(bis);  
  25.         return ois.readObject();  
  26.     }  
  27.   
  28.     public String getString() {  
  29.         return string;  
  30.     }  
  31.   
  32.     public void setString(String string) {  
  33.         this.string = string;  
  34.     }  
  35.   
  36.     public SerializableObject getObj() {  
  37.         return obj;  
  38.     }  
  39.   
  40.     public void setObj(SerializableObject obj) {  
  41.         this.obj = obj;  
  42.     }


  43. class SerializableObject implements Serializable {  
  44.     private static final long serialVersionUID = 1L;  


六、适配模式

1、类的适配模式 :当希望将一个类转换成满足另一个新接口的类时,可以使用类的适配器模式,创建一个新类,继承原有的类,实现新的接口即可。

                                   (接口A 有 两个b 、c  两个 方法 ,A的实现类B实现A的b方法,没有实现A的c方法   因为B继承了C类,C类中有c方法  )

  1. public class AdapterTest {  
  2.     public static void main(String[] args) {  
  3.         Targetable target = new Adapter();  
  4.         target.method1();  
  5.         target.method2();  
  6.     }  

2、对象的适配器模式:当希望将一个对象转换成满足另一个新接口的对象时,可以创建一个Wrapper类,持有原类的一个实例,在Wrapper类的方法中,调用实例的方法就   

                                            行。

                                            (接口A 有 两个b 、c  两个 方法,A的实现类B实现A的b 、c 方法,但B类中有C类的实例对象 ,实现的 c 方法 中 具体是C类对象的方法 )


3、接口适配器模式:  借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系,

                                         所以我们写一个类,继承该抽象类,重写我们需要的方法就行

                                       (避免一个类要是实现 其实现接口的所有方法)

  1. public class WrapperTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.         Sourceable source1 = new SourceSub1();  
  5.         Sourceable source2 = new SourceSub2();  
  6.           
  7.         source1.method1();  
  8.         source1.method2();  
  9.         source2.method1();  
  10.         source2.method2();  
  11.     }  
  12. }  

7、装饰模式:顾名思义,装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例

  1. public class Decorator implements Sourceable {  
  2.   
  3.     private Sourceable source;  
  4.       
  5.     public Decorator(Sourceable source){  
  6.         super();  
  7.         this.source = source;  
  8.     }  
  9.     @Override  
  10.     public void method() {  
  11.         System.out.println("before decorator!");  
  12.         source.method();  
  13.         System.out.println("after decorator!");  
  14.     }  
  15. }  

测试类:

  1. public class DecoratorTest {  
  2.     public static void main(String[] args) {  
  3.         Sourceable source = new Source();  
  4.         Sourceable obj = new Decorator(source);  
  5.         obj.method();  
  6.     }  

八、代理模式:代理模式就是多一个代理类出来,替原对象进行一些操作 (想先AOP 切面就容易理解了, 其实也类似 装饰 模式)

  1. public class Proxy implements Sourceable { 

  2.     private Source source;  
  3.     public Proxy(){  
  4.         super();  
  5.         this.source = new Source();  
  6.     }  
  7.     @Override  
  8.     public void method() {  
  9.         before();  
  10.         source.method();  
  11.         atfer();  
  12.     }  
  13.     private void atfer() {  
  14.         System.out.println("after proxy!");  
  15.     }  
  16.     private void before() {  
  17.         System.out.println("before proxy!");  
  18.     }  
  19. }  

测试类:

public class ProxyTest {  

  1.     public static void main(String[] args) {  
  2.         Sourceable source = new Proxy();  
  3.         source.method();  
  4.     }  
  5.   
  6. }  

输出:

before proxy!
the original method!
after proxy!


九、外观模式:外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,

                            而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口

                           (其实就是将多个类 及 类的 方法整合到一个 类中同一管理 , 下面举例:电脑的启动关闭 (cup,内存,硬盘))

  1. public class Computer {  
  2.     private CPU cpu;  
  3.     private Memory memory;  
  4.     private Disk disk;  
  5.       
  6.     public Computer(){  
  7.         cpu = new CPU();  
  8.         memory = new Memory();  
  9.         disk = new Disk();  
  10.     }
  11.     public void startup(){  
  12.         System.out.println("start the computer!");  
  13.         cpu.startup();  
  14.         memory.startup();  
  15.         disk.startup();  
  16.         System.out.println("start computer finished!");  
  17.     }  
  18.     public void shutdown(){  
  19.         System.out.println("begin to close the computer!");  
  20.         cpu.shutdown();  
  21.         memory.shutdown();  
  22.         disk.shutdown();  
  23.         System.out.println("computer closed!");  
  24.     }  
  25. }  

User类如下:

  1. public class User {  
  2.     public static void main(String[] args) {  
  3.         Computer computer = new Computer();  
  4.         computer.startup();  
  5.         computer.shutdown();  
  6.     }  
  7. }  

输出:

start the computer!
cpu startup!
memory startup!
disk startup!
start computer finished!
begin to close the computer!
cpu shutdown!
memory shutdown!
disk shutdown!
computer closed!


十、桥接模式: 将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,

                             在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,

                             每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。

  1. public abstract class Bridge {     //定义一个桥
  2.     private Sourceable source;     //这是一个接口
  3.   
  4.     public void method(){  
  5.         source.method();  
  6.     }  
  7.       
  8.     public Sourceable getSource() {  
  9.         return source;  
  10.     }  
  11.   
  12.     public void setSource(Sourceable source) {  
  13.         this.source = source;  
  14.     }  

测试类:

  1. public class BridgeTest {  
  2.     public static void main(String[] args) {  
  3.           
  4.         Bridge bridge = new MyBridge();  
  5.           
  6.         /*调用第一个对象*/  
  7.         Sourceable source1 = new SourceSub1();  
  8.         bridge.setSource(source1);  
  9.         bridge.method();  
  10.           
  11.         /*调用第二个对象*/  
  12.         Sourceable source2 = new SourceSub2();  
  13.         bridge.setSource(source2);  
  14.         bridge.method();  
  15.     }  
  16. }  

output:

this is the first sub!
this is the second sub!









评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值