Java设计模式总结

Posted AlexP5

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java设计模式总结相关的知识,希望对你有一定的参考价值。

一、创建型模式(CreationalPatterns)

1.Builder

(1)模式名称

生成器模式

 

(2)意图及适用场景

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

以下情况适用Builder模式

l  当创建复杂对象的算法应该独立于与该对象的组成部分以及他们的装配

方式时。

l  当构造过程必须被构造的对象有不同的表示时。

 

(3)结构

 

(4)实现

//抽象产品类,使用了模板方法模式,不同产品有不同的“组成部分part” 
abstract class AbstractProduct 
  protected abstract void part01(); 
  protected abstract void part02(); 
  protected abstract void part03(); 
    
  //模板方法给出了默认的组装方式,生成默认的产品 
  public final AbstractProduct defaultProduct()  
    part01(); 
    part02(); 
    part03(); 
    return this;//返回当前对象,即默认组装方式的产品 
   
 

//具体的产品A、B,不同产品实现了不同的“组成部分part” 
class ConcreteProductA extends AbstractProduct 
  protected void part01()  
    System.out.println("产品A :part01() ..."); 
   
  protected void part02()  
    System.out.println("产品A :part02() ..."); 
   
  protected void part03()  
    System.out.println("产品A :part03() ..."); 
   
 

class ConcreteProductB extends AbstractProduct 
  protected void part01()  
    System.out.println("产品B :part01() ..."); 
   
  protected void part02()  
    System.out.println("产品B :part02() ..."); 
   
  protected void part03()  
    System.out.println("产品B :part03() ..."); 
   
 

//抽象建造者,制定每一种产品应该实现的组合方式buildPart()和生产buildProduct()的标准 
abstract class AbstractBuilder 
  public abstract void buildPart(); 
  public abstract AbstractProduct buildProduct(); 
 


/* 
* 具体建造者,如果对于默认产品(即当调用抽象产品中的defaultProduct()方法)不满意时, 
* 可以不调用它来获得产品,而是使用具体的建造者来改变产品的生产组装方式,以得到不同的产品 
*/ 
class ConcreteBuilderA extends AbstractBuilder 
  private AbstractProductproductA = new ConcreteProductA(); 
    
  public void buildPart()  
    this.productA.part03(); 
    this.productA.part02(); 
    this.productA.part01(); 
   
    
  public AbstractProductbuildProduct()  
    return this.productA; 
   
 

class ConcreteBuilderB extends AbstractBuilder 
  private AbstractProductproductB = new ConcreteProductB(); 
    
  public void buildPart()  
    this.productB.part02(); 
    this.productB.part01(); 
    //特地省略掉产品B中的一个组成部分,例如该部分的功能顾客不需要 
//    this.productB.part03(); 
   
    
  public AbstractProductbuildProduct()  
    return this.productB; 
   
 

//导演类,预先持有各个产品的建造者,为需要不同于默认产品的用户提供不同的组装方式 
class Director 
  private AbstractBuilderbuilderA = new ConcreteBuilderA(); 
  private AbstractBuilderbuilderB = new ConcreteBuilderB();    
    
  public AbstractProductgetProductA()  
    this.builderA.buildPart(); 
    return this.builderA.buildProduct(); 
   
    
  public AbstractProductgetProductB()  
    this.builderB.buildPart(); 
    return this.builderB.buildProduct(); 
   
 

//测试类 
public class Client  
  public static void main(String[]args)  
    System.out.println("利用模板方法模式获得默认的产品A"); 
    AbstractProduct defualtProductA = new ConcreteProductA().defaultProduct();    
     
    System.out.println("\\n利用Director类获得不同组装方式的产品A"); 
    Director director = new Director(); 
    director.getProductA(); 
     
    System.out.println("\\n利用Director类获得不同组装方式的产品B"); 
    director.getProductB(); 
   

测试结果:

利用模板方法模式获得默认的产品A

产品A :part01() ...

产品A :part02() ...

产品A :part03() ...

利用Director类获得不同组装方式的产品A

产品A :part03() ...

产品A :part02() ...

产品A :part01() ...

利用Director类获得不同组装方式的产品B

产品B :part02() ...

产品B :part01() ...


2.Factory

(1)模式名称

工厂方法模式(别名:虚构造器)

 

(2)意图及适用场景

定义一个用户创建对象的接口,让子类决定实例化哪一个类。Factory Method使一个类的实例化延迟到其子类

以下情况可使用FactoryMethod模式

l  当一个类不知道它所必须创建的对象的类的时候

l  当一个类希望由它的子类来指定它所创建的对象的时候

l  当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将  

哪一个帮助子类是代理者这一信息局部化的时候。

 

(3)结构

 



  interface IProduct  
    public void method01(); 
    public void method02(); 
   
    
  // 具体的产品实现类 
  class ConcreteProductA implements IProduct  
    public void method01()  
      System.out.println("ConcreteProductAmethod01() ..."); 
     
    public void method02()  
      System.out.println("ConcreteProductAmethod02() ..."); 
     
   
    
  class ConcreteProductB implements IProduct  
    public void method01()  
      System.out.println("ConcreteProductBmethod01() ..."); 
     
    
    public void method02()  
      System.out.println("ConcreteProductBmethod02() ..."); 
     
   
    
  // 抽象的工厂类,定义了其子类必须实现的createProduct()方法 
  abstract class Factory  
    //运用了Java 中的泛型和反射技术 
    public abstract <T extends IProduct> T createProduct(Class<T> c); 
   
    
  class ConcreteFactory extends Factory  
    public <T extends IProduct>T createProduct(Class<T> c)  
      T product = null; 
      try  
        product = (T)Class.forName(c.getName()).newInstance(); 
       catch (Exception e)  
        e.printStackTrace(); 
       
      return product; 
     
   
    
  public class Client  
    public static void main(String[]args)  
      //创建一个具体工厂 
      Factory factory = new ConcreteFactory(); 
      //根据参数中具体产品的.class名称来决定创建的产品类型 
      IProduct product01 =factory.createProduct(ConcreteProductA.class); 
      IProduct product02 =factory.createProduct(ConcreteProductB.class); 
        
      product01.method01(); 
      product01.method02(); 
      product02.method01(); 
      product02.method02(); 
     



测试结果:

ConcreteProductA method01() ...

ConcreteProductA method02() ...

ConcreteProductB method01() ...

ConcreteProductB method02() ...

 

3.Singleton

(1)模式名称

单例模式

 

(2)意图及适用场景

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

下面情况可以使用Singleton模式:

l  当一个类只能有一个实例且客户可以从一个众所周知的访问点访问它

时。

l  当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代

码就能使用一个扩展的实例时。

 

(3)结构


(4)实现

class Teacher 
    private staticTeacher teacher = null;// 声明一个Teacher类的引用
    privateTeacher() // 将构造方法私有
    
    public staticTeacher getInstance() // 实例化引用
        if (teacher== null) 
          teacher = new Teacher();
        
        returnteacher;
    
    public voidgetName() // 使用普通方法输出teacher
       System.out.println("I'm a teacher");
    

public class Test 
    public staticvoid main(String[] args) 
       System.out.print("teacher1:");
        Teacherteacher1 = Teacher.getInstance();
       teacher1.getName();
       System.out.print("teacher2:");
        Teacherteacher2 = Teacher.getInstance();
       teacher2.getName();
       System.out.print("teacher3:");
        Teacherteacher3 = Teacher.getInstance();
       teacher3.getName();
    


测试结果:

teacher1:I'm a teacher

teacher2:I'm a teacher

teacher3:I'm a teacher

 

二、结构型模式(StructuralPatterns)

1.Adapter

(1)模式名称

适配器模式

 

(2)意图及适用场景

将一个类的接口转换成客户希望的另一个接口。

Adapter的适用场景有:

l  想要使用某个已经存在的类,而它的接口不符合需求。

l  想要创建一个可复用的类,该类可以和其他部相关的类或不可预见的类

协同工作。

l  想要使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹

配他们的接口。对象的适配器可以适配它父类的接口。

 

(3)结构

适配器使用多重继承对一个接口与另一个接口进行匹配(类适配器):

 

 

 对象匹配依赖于对象组合(对象适配器):


(4)实现

类适配器:

// 已存在的、具有特殊功能、但不符合我们既有的标准接口的类  
class Adaptee   
    public void specificRequest()   
        System.out.println("被适配类具有 特殊功能...");  
      
  
  
// 目标接口,或称为标准接口  
interface Target   
    public void request();  
  
  
// 具体目标类,只提供普通功能  
class ConcreteTarget implements Target   
    public void request()   
        System.out.println("普通类 具有 普通功能...");  
      
  
   
// 适配器类,继承了被适配类,同时实现标准接口  
class Adapter extends Adaptee implements Target  
    public void request()   
        super.specificRequest();  
      
  
   
// 测试类public class Client   
    public static void main(String[] args)   
        // 使用普通功能类  
        Target concreteTarget = new ConcreteTarget();  
        concreteTarget.request();  
          
        // 使用特殊功能类,即适配类  
        Target adapter = new Adapter();  
        adapter.request();  
      
  


对象适配器:

// 适配器类,直接关联被适配类,同时实现标准接口 
class Adapter implements Target 
    // 直接关联被适配类 
    private Adapteeadaptee; 
     
    // 可以通过构造函数传入具体需要适配的被适配类对象 
    public Adapter(Adaptee adaptee)  
       this.adaptee = adaptee; 
     
     
    public voidrequest()  
        // 这里是使用委托的方式完成特殊功能 
       this.adaptee.specificRequest(); 
     
 
 
// 测试类 
public class Client  
    public staticvoid main(String[] args)  
        // 使用普通功能类 
        TargetconcreteTarget = new ConcreteTarget(); 
       concreteTarget.request(); 
         
        // 使用特殊功能类,即适配类, 
        // 需要先创建一个被适配类的对象作为参数 
        Targetadapter = new Adapter(new Adaptee()); 
       adapter.request(); 
     
 

 测试结果:

普通类 具有 普通功能... 

被适配类具有 特殊功能... 

 

 2.Composite

(1)模式名称

组合模式

 

(2)意图及适用场景

将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

以下情况使用Composite模式:

l  你想要表示对象的部分-整体层次结构。

l  你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结

构中的所有对象。

 

(3)结构


 

(4)实现

public classPayDemo  
    public abstract class Market  
        String name; 
 
        public abstract void add(Marketm); 
        public abstract void remove(Marketm); 
        public abstract void PayByCard(); 
     
 
  
 // 分店 下面可以有加盟店 
    public class MarketBranch extends Market 
        // 加盟店列表 
        List<Market> list = newArrayList<PayDemo.Market>(); 
 
        public MarketBranch(String s)  
            this.name = s; 
         
 
        @Override 
        public void add(Market m)   
            list.add(m); 
         
 
        @Override 
        public void remove(Market m)  
            list.remove(m); 
         
 
        // 消费之后,该分店下的加盟店自动累加积分 
        @Override 
        public void PayByCard()  
            System.out.println(name + "消费,积分已累加入该会员卡"); 
            for (Market m : list)  
                m.PayByCard(); 
             
         
     
 
    // 加盟店 下面不在有分店和加盟店,最底层 
    public class MarketJoin extends Market 
        public MarketJoin(String s)  
            this.name = s; 
         
 
        @Override 
        public void add(Market m)  
         
 
        @Override 
        public void remove(Market m)  
         
 
        @Override 
        public void PayByCard()  
            // TODO Auto-generated methodstub 
            System.out.println(name + "消费,积分已累加入该会员卡"); 
         
     
 
    public static void main(String[] args) 
        PayDemo demo = new PayDemo(); 
        MarketBranch rootBranch = demo.newMarketBranch("总店"); 
        MarketBranch xaBranch = demo.newMarketBranch("西安市分店"); 
        MarketJoin join1 = demo.newMarketJoin("西安市长安区加盟店"); 
        MarketJoin join2 = demo.newMarketJoin("西安市雁塔区加盟店"); 
         
        xaBranch.add(join1); 
        xaBranch.add(join2); 
        rootBranch.add(xaBranch); 
        rootBranch.PayByCard(); 
     
 

测试结果:

总店消费,积分已累加入该会员卡

西安市分店消费,积分已累加入该会员卡

西安市长安区加盟店消费,积分已累加入该会员卡

西安市雁塔区加盟店消费,积分已累加入该会员卡

 

3.Proxy

(1)模式名称

代理模式

 

(2)意图及适用场景

为其他对象提供一种代理以控制对这个对象的访问。

Proxy适用场景有:

l  远程代理(Remote Proxy) -可以隐藏一个对象存在于不同地址空间的事

实。也使得 客户端可以访问在远程机器上的对象,远程机器可能具有

更好的计算性能与处理速度,可以快速响应并处理客户端请求。

l  虚拟代理(Virtual Proxy) – 允许内存开销较大的对象在需要的时候

创建。只有我们真正需要这个对象的时候才创建。

l  写入时复制代理(Copy-On-Write Proxy) – 用来控制对象的复制,方

法是延迟对象的复制,直到客户真的需要为止。是虚拟代理的一个变

体。

l  保护代理(Protection (Access)Proxy) – 为不同的客户提供不同级别

的目标对象访问权限。

 

(3)结构

 

(4)实现

/**
 * 抽象主题,定义主要功能
 */
Publicinterface Subject 
   Publicvoid operate();

 
/**
 * 具体主题
 */
Publicclass RealSubject implements Subject
 
   @Override
   Publicvoid operate() 
        System.out.println("RealSubjectoperate started......");
   

 
/**
 * 代理类
 */
Publicclass Proxy implements Subject
 
   private Subject subject;
 
   public Proxy(Subjectsubject) 
        this.subject =subject;
   
 
   @Override
   Publicvoid operate() 
        System.out.println("Beforeoperate......");
        subject.operate();
        System.out.println("Afteroperate......");
   

 
/**
 * 客户
 */
Public class Client
   /**
    * @param args
    */
   Publicstatic void main(String[] args) 
        Subjectsubject = new RealSubject();
        Proxyproxy = new Proxy(subject);
        proxy.operate();
   

测试结果:

 Beforeoperate......

RealSubjectoperate started......

Afteroperate......

 

 

三、行为型模式(BehavioralPatterns)

1.Command

(1)模式名称

命令模式(别名:动作、事务)

 

 (2)意图及适用场景

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

Command适用于:

l  整个调用过程比较繁杂,或者存在多处这种调用。这时,使用Command

类对该调用加以封装,便于功能的再利用。

l  调用前后需要对调用参数进行某些处理。

l  调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等。

 

(3)结构



(4)实现

class Invoker 
    private Command command; 
    public void setCommand(Command command) 
        this.command = command; 
     
    public void action() 
        this.command.execute(); 
     
 
 
abstract classCommand  
    public abstract void execute(); 
 
 
classConcreteCommand extends Command  
    private Receiver receiver; 
    public ConcreteCommand(Receiverreceiver) 
        this.receiver = receiver; 
     
    public void execute()  
        this.receiver.doSomething(); 
     
 
 
class Receiver 
    public void doSomething() 
        System.out.println("接受者-业务逻辑处理"); 
     
 
 
public classClient  
    public static void main(String[]args) 
        Receiver receiver = newReceiver(); 
        Command command = newConcreteCommand(receiver); 
        System.out.print("客户端直接执行具体命令方式:");
        command.execute(); 
 
        System.out.print("客户端通过调用者来执行命令:");
        Invoker invoker = new Invoker(); 
        invoker.setCommand(command); 
        invoker.action(); 
     
 

测试结果:

客户端直接执行具体命令方式:接受者-业务逻辑处理

客户端通过调用者来执行命令:接受者-业务逻辑处理

 

2.Observer

(1)模式名称

观察者模式

 

(2)意图及适用场景

定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象得到通知并被自动更新。

Observer的适用场景有:

l  当一个抽象模型有两个方面,其中一个方面依赖于另一方面。

l  当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象

有待改变。

l  当一个对象必须通知其它对象,而它又不能假定其它对象是谁。

 

(3)结构


 

(4)实现

public interfaceObserver

    public void update(float temprature);


public class ConcreteObserver implements Observer

    private float temperature;
    private final Subject subject;

    public ConcreteObserver(final Subject subject)
    
        this.subject = subject;
        this.subject.registerObserver(this);
    

    public float getTemperature()
    
        return temperature;
    

    public void setTemperature(final float temperature)
    
        this.temperature = temperature;
    

    @Override
    public void update(final float temperature)
    
        this.temperature = temperature;
    


public interface Subject

    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObservers();


public class ConcreteSubject implements Subject

    private final List<Observer> observers;
    private float temperature;
    public float getTemperature()
    
        return temperature;
    

    private void temperatureChanged()
    
        this.notifyObservers();
    

    public void setTemperature(final float temperature)
    
        this.temperature = temperature;
        this.temperatureChanged();
    

    public ConcreteSubject()
    
        observers = new ArrayList<Observer>();
    

    @Override
    public void registerObserver(final Observer o)
    
        observers.add(o);
    

    @Override
    public void removeObserver(final Observer o)
    
        if (observers.indexOf(o) >= 0)
        
            observers.remove(o);
        
    

    @Override
    public void notifyObservers()
    
        for (final Observer o : observers)
        
            o.update(temperature);
        
    

 
public class Client

   public static void main(final String[] args)
    
       final ConcreteSubject sb = new ConcreteSubject();
       sb.setTemperature((float) 20.00);
      System.out.println("温度:"+sb.getTemperature()+"℃");
 
       final Observer o = new ConcreteObserver(sb);
       sb.setTemperature((float) 21.00);
       System.out.println("温度:"+sb.getTemperature()+"℃");
    

测试结果:

温度:20.0℃

温度:21.0℃

 

3.Visitor

(1)模式名称

访问者模式

 

(2)意图及适用场景

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下作用于这些元素的新操作。

在下列情况下使用Visitor模式:

l  一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象

实施一些依赖于其具体类的操作。

l  需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你

想避免让这些操作“污染”这些对象的类。 Visitor使得你可以将相

关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,

用Visitor模式让每个应用仅包含需要用到的操作。

l  定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改

变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代

价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。

 

(3)结构

 

 

(4)实现

interface Service 
      public voidaccept(Visitor visitor);

 
class Visitor 
 
      public voidprocess(Service service) 
           System.out.println("基本业务");
      
 
      public voidprocess(Saving service) 
           System.out.println("存款");
      
 
      public voidprocess(Draw service) 
           System.out.println("提款");
      
 
      public voidprocess(Fund service) 
           System.out.println("基金");
      
 

 
class Saving implements Service 
      public voidaccept(Visitor visitor) 
           visitor.process(this);
      

 
class Draw implements Service 
      public voidaccept(Visitor visitor) 
           visitor.process(this);
      

 
class Fund implements Service 
      public voidaccept(Visitor visitor) 
           visitor.process(this);
      

 
public class Client 
      public staticvoid main(final String[] args) 
           Servicesaving = new Saving();
           Servicefund = new Fund();
           Servicedraw = new Draw();
           Visitorvisitor = new Visitor();
           saving.accept(visitor);
           fund.accept(visitor);
           draw.accept(visitor);
      


测试结果:

存款

基金

提款

以上是关于Java设计模式总结的主要内容,如果未能解决你的问题,请参考以下文章

Lucene简单总结

开启加盟模式,喜茶能否借此越过山丘?

快递行业疯狂压榨快递小哥和加盟商,可能正往末路狂飙

无人超市无人便利店加盟代理新零售模式分析

基于唯一键的Django加盟模式

设计模式之工厂模式