美文网首页
设计模式

设计模式

作者: ccccaixiaohao | 来源:发表于2020-08-20 11:09 被阅读0次

参考地址:http://c.biancheng.net/view/1317.html

1.分类

1.按目的分类

1.创建型模式:用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。GoF 中提供了单例、原型、工厂方法、抽象工厂、建造者等 5 种创建型模式。

2.结构型模式:用于描述如何将类或对象按某种布局组成更大的结构,GoF 中提供了代理、适配器、桥接、装饰、外观、享元、组合等 7 种结构型模式。

3.行为型模式:用于描述类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。GoF 中提供了模板方法、策略、命令、职责链、状态、观察者、中介者、迭代器、访问者、备忘录、解释器等 11 种行为型模式。

2.根据作用范围

1.类模式:用于处理类与子类之间的关系,这些关系通过继承来建立,是静态的,在编译时刻便确定下来了。GoF中的工厂方法、(类)适配器、模板方法、解释器属于该模式。

2.对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。GoF 中除了以上 4 种,其他的都是对象模式。

2.设计模式各种功能

1.单例(Singleton)模式:某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
2.原型(Prototype)模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
3.工厂方法(Factory Method)模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
4.抽象工厂(AbstractFactory)模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
5.建造者(Builder)模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
6.代理(Proxy)模式:为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
7.适配器(Adapter)模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
8.桥接(Bridge)模式:将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
9.装饰(Decorator)模式:动态的给对象增加一些职责,即增加其额外的功能。
10.外观(Facade)模式:为多个复杂的子系统提供一个一致的接口,使这些子系统更加容易被访问。
11.享元(Flyweight)模式:运用共享技术来有效地支持大量细粒度对象的复用。
12.组合(Composite)模式:将对象组合成树状层次结构,使用户对单个对象和组合对象具有一致的访问性。
13.模板方法(TemplateMethod)模式:定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
14.策略(Strategy)模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
15.命令(Command)模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
16.职责链(Chain of Responsibility)模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
17.状态(State)模式:允许一个对象在其内部状态发生改变时改变其行为能力。
18.观察者(Observer)模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
19.中介者(Mediator)模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
20.迭代器(Iterator)模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
21.访问者(Visitor)模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
22.备忘录(Memento)模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
23.解释器(Interpreter)模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。

3.具体设计模式

------创建型模式-------

1.单例模式

1.定义与特点

单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。

单例模式有 3 个特点:
1.单例类只有一个实例对象;
2.该单例对象必须由单例类自行创建;
3.单例类对外提供一个访问该单例的全局访问点;

2.模式的实现

懒汉式

public class LazySingleton
{
    private static volatile LazySingleton instance=null;    //保证 instance 在所有线程中同步
    private LazySingleton(){}    //private 避免类在外部被实例化
    public static synchronized LazySingleton getInstance()
    {
        //getInstance 方法前加同步
        if(instance==null)
        {
            instance=new LazySingleton();
        }
        return instance;
    }
}

饿汉式

public class HungrySingleton
{
    private static final HungrySingleton instance=new HungrySingleton();
    private HungrySingleton(){}
    public static HungrySingleton getInstance()
    {
        return instance;
    }
}
3.应用场景

1.在应用场景中,某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
2.当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。
3.当某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。

2.原型模式

1.定义与特点

用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
1.抽象原型类:规定了具体原型对象必须实现的接口。
2.具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
3.访问类:使用具体原型类中的 clone() 方法来复制新的对象。

2.模式的实现
public class ProtoTypeCitation
{
    public static void main(String[] args) throws CloneNotSupportedException
    {
        citation obj1=new citation("张三","同学:在2016学年第一学期中表现优秀,被评为三好学生。","韶关学院");
        obj1.display();
        citation obj2=(citation) obj1.clone();
        obj2.setName("李四"); 
        obj2.display();
    }
}
//奖状类
class citation implements Cloneable
{
    String name;
    String info;
    String college;
    citation(String name,String info,String college)
    {
        this.name=name;
        this.info=info;
        this.college=college;
        System.out.println("奖状创建成功!");
    }
    void setName(String name)
    {
        this.name=name;
    }
    String getName()
    {
        return(this.name);
    }
    void display()
    {
        System.out.println(name+info+college);
    }
    public Object clone() throws CloneNotSupportedException
    {
        System.out.println("奖状拷贝成功!");
        return (citation)super.clone();
    }
}
3.应用场景

1.对象之间相同或相似,即只是个别的几个属性不同的时候。
2.对象的创建过程比较麻烦,但复制比较简单的时候。

3.工厂模式

1.定义与特点

定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。

1.用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
2.在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

其缺点是:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

2.模式的实现
package FactoryMethod;
public class AbstractFactoryTest
{
    public static void main(String[] args)
    {
        try
        {
            Product a;
            AbstractFactory af;
            af=(AbstractFactory) ReadXML1.getObject();
            a=af.newProduct();
            a.show();
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}
//抽象产品:提供了产品的接口
interface Product
{
    public void show();
}
//具体产品1:实现抽象产品中的抽象方法
class ConcreteProduct1 implements Product
{
    public void show()
    {
        System.out.println("具体产品1显示...");
    }
}
//具体产品2:实现抽象产品中的抽象方法
class ConcreteProduct2 implements Product
{
    public void show()
    {
        System.out.println("具体产品2显示...");
    }
}
//抽象工厂:提供了厂品的生成方法
interface AbstractFactory
{
    public Product newProduct();
}
//具体工厂1:实现了厂品的生成方法
class ConcreteFactory1 implements AbstractFactory
{
    public Product newProduct()
    {
        System.out.println("具体工厂1生成-->具体产品1...");
        return new ConcreteProduct1();
    }
}
//具体工厂2:实现了厂品的生成方法
class ConcreteFactory2 implements AbstractFactory
{
    public Product newProduct()
    {
        System.out.println("具体工厂2生成-->具体产品2...");
        return new ConcreteProduct2();
    }
}
3.应用场景

1.客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
2.创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
3.客户不关心创建产品的细节,只关心产品的品牌。

4.抽象工厂模式

1.定义与特点

是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
1.可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
2.当增加一个新的产品族时不需要修改原代码,满足开闭原则。

2.模式的实现
package AbstractFactory;
import java.awt.*;
import javax.swing.*;
public class FarmTest
{
    public static void main(String[] args)
    {
        try
        {          
            Farm f;
            Animal a;
            Plant p;
            f=(Farm) ReadXML.getObject();
            a=f.newAnimal();
            p=f.newPlant();
            a.show();
            p.show();
        }
        catch(Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}
//抽象产品:动物类
interface Animal
{
    public void show();
}
//具体产品:马类
class Horse implements Animal
{
    JScrollPane sp;
    JFrame jf=new JFrame("抽象工厂模式测试");
    public Horse()
    {
        Container contentPane=jf.getContentPane();
        JPanel p1=new JPanel();
        p1.setLayout(new GridLayout(1,1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
        sp=new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1=new JLabel(new ImageIcon("src/A_Horse.jpg"));
        p1.add(l1);       
        jf.pack();       
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
    }
    public void show()
    {
        jf.setVisible(true);
    }
}
//具体产品:牛类
class Cattle implements Animal
{
    JScrollPane sp;
    JFrame jf=new JFrame("抽象工厂模式测试");
    public Cattle() {
        Container contentPane=jf.getContentPane();
        JPanel p1=new JPanel();
        p1.setLayout(new GridLayout(1,1));
        p1.setBorder(BorderFactory.createTitledBorder("动物:牛"));
        sp=new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1=new JLabel(new ImageIcon("src/A_Cattle.jpg"));
        p1.add(l1);       
        jf.pack();       
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
    }
    public void show()
    {
        jf.setVisible(true);
    }
}
//抽象产品:植物类
interface Plant
{
    public void show();
}
//具体产品:水果类
class Fruitage implements Plant
{
    JScrollPane sp;
    JFrame jf=new JFrame("抽象工厂模式测试");
    public Fruitage()
    {
        Container contentPane=jf.getContentPane();
        JPanel p1=new JPanel();
        p1.setLayout(new GridLayout(1,1));
        p1.setBorder(BorderFactory.createTitledBorder("植物:水果"));
        sp=new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1=new JLabel(new ImageIcon("src/P_Fruitage.jpg"));
        p1.add(l1);       
        jf.pack();       
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
    }
    public void show()
    {
        jf.setVisible(true);
    }
}
//具体产品:蔬菜类
class Vegetables implements Plant
{
    JScrollPane sp;
    JFrame jf=new JFrame("抽象工厂模式测试");
    public Vegetables()
    {
        Container contentPane=jf.getContentPane();
        JPanel p1=new JPanel();
        p1.setLayout(new GridLayout(1,1));
        p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));
        sp=new JScrollPane(p1);
        contentPane.add(sp, BorderLayout.CENTER);
        JLabel l1=new JLabel(new ImageIcon("src/P_Vegetables.jpg"));
        p1.add(l1);       
        jf.pack();       
        jf.setVisible(false);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭 
    }
    public void show()
    {
        jf.setVisible(true);
    }
}
//抽象工厂:农场类
interface Farm
{
    public Animal newAnimal();
    public Plant newPlant();
}
//具体工厂:韶关农场类
class SGfarm implements Farm
{
    public Animal newAnimal()
    {
        System.out.println("新牛出生!");
        return new Cattle();
    }
    public Plant newPlant()
    {
        System.out.println("蔬菜长成!");
        return new Vegetables();
    }
}
//具体工厂:上饶农场类
class SRfarm implements Farm
{
    public Animal newAnimal()
    {
        System.out.println("新马出生!");
        return new Horse();
    }
    public Plant newPlant()
    {
        System.out.println("水果长成!");
        return new Fruitage();
    }
}
3.应用场景

1.当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
2.系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
3.系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。

5.建造者模式

1.定义与特点

指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
1.各个具体的建造者相互独立,有利于系统的扩展。
2.客户端不必知道产品内部组成的细节,便于控制细节风险。

2.模式的实现

产品角色:包含多个组成部件的复杂对象。

class Product
{
    private String partA;
    private String partB;
    private String partC;
    public void setPartA(String partA)
    {
        this.partA=partA;
    }
    public void setPartB(String partB)
    {
        this.partB=partB;
    }
    public void setPartC(String partC)
    {
        this.partC=partC;
    }
    public void show()
    {
        //显示产品的特性
    }
}

抽象建造者:包含创建产品各个子部件的抽象方法

abstract class Builder
{
    //创建产品对象
    protected Product product=new Product();
    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();
    //返回产品对象
    public Product getResult()
    {
        return product;
    }
}

具体建造者:实现了抽象建造者接口。

public class ConcreteBuilder extends Builder
{
    public void buildPartA()
    {
        product.setPartA("建造 PartA");
    }
    public void buildPartB()
    {
        product.setPartA("建造 PartB");
    }
    public void buildPartC()
    {
        product.setPartA("建造 PartC");
    }
}

指挥者:调用建造者中的方法完成复杂对象的创建。

class Director
{
    private Builder builder;
    public Director(Builder builder)
    {
        this.builder=builder;
    }
    //产品构建与组装方法
    public Product construct()
    {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}

客户类。

public class Client
{
    public static void main(String[] args)
    {
        Builder builder=new ConcreteBuilder();
        Director director=new Director(builder);
        Product product=director.construct();
        product.show();
    }
}
3.应用场景

建造者(Builder)模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定,所以它通常在以下场合使用。
1.创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
2.创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。

------结构型模式-------

1.代理模式

1.定义与特点

代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

代理模式的主要优点有:
1.代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
2.代理对象可以扩展目标对象的功能;
3.代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;

其主要缺点是:
1.在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
2.增加了系统的复杂度;

2.模式的实现
package proxy;
public class ProxyTest
{
    public static void main(String[] args)
    {
        Proxy proxy=new Proxy();
        proxy.Request();
    }
}
//抽象主题
interface Subject
{
    void Request();
}
//真实主题
class RealSubject implements Subject
{
    public void Request()
    {
        System.out.println("访问真实主题方法...");
    }
}
//代理
class Proxy implements Subject
{
    private RealSubject realSubject;
    public void Request()
    {
        if (realSubject==null)
        {
            realSubject=new RealSubject();
        }
        preRequest();
        realSubject.Request();
        postRequest();
    }
    public void preRequest()
    {
        System.out.println("访问真实主题之前的预处理。");
    }
    public void postRequest()
    {
        System.out.println("访问真实主题之后的后续处理。");
    }
}
3.应用场景

1.远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
2.虚拟代理,这种方式通常用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,因某种计算比较复杂而短时间无法完成,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
3.安全代理,这种方式通常用于控制不同种类客户对真实对象的访问权限。
4.智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它。

  1. 延迟加载,指为了提高系统的性能,延迟对目标的加载。例如,[Hibernate] 中就存在属性的延迟加载和关联表的延时加载。

2.装饰模式

1.定义与特点

装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

装饰(Decorator)模式的主要优点有:
1.采用装饰模式扩展对象的功能比采用继承方式更加灵活。
2.可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。
其主要缺点是:装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。

2.模式的实现
package decorator;
public class DecoratorPattern
{
    public static void main(String[] args)
    {
        Component p=new ConcreteComponent();
        p.operation();
        System.out.println("---------------------------------");
        Component d=new ConcreteDecorator(p);
        d.operation();
    }
}
//抽象构件角色
interface  Component
{
    public void operation();
}
//具体构件角色
class ConcreteComponent implements Component
{
    public ConcreteComponent()
    {
        System.out.println("创建具体构件角色");       
    }   
    public void operation()
    {
        System.out.println("调用具体构件角色的方法operation()");           
    }
}
//抽象装饰角色
class Decorator implements Component
{
    private Component component;   
    public Decorator(Component component)
    {
        this.component=component;
    }   
    public void operation()
    {
        component.operation();
    }
}
//具体装饰角色
class ConcreteDecorator extends Decorator
{
    public ConcreteDecorator(Component component)
    {
        super(component);
    }   
    public void operation()
    {
        super.operation();
        addedFunction();
    }
    public void addedFunction()
    {
        System.out.println("为具体构件角色增加额外的功能addedFunction()");           
    }
}
3.应用场景

1.当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。
2.当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。
3.当对象的功能要求可以动态地添加,也可以再动态地撤销时。

3.外观模式

1.定义与特点

外观(Facade)模式的定义:是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。

外观(Facade)模式是“迪米特法则”的典型应用,它有以下主要优点。
1.降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。
2.对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。
3.降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象。

外观(Facade)模式的主要缺点如下。
1.不能很好地限制客户使用子系统类。
2.增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

2.模式的实现
package facade;
public class FacadePattern
{
    public static void main(String[] args)
    {
        Facade f=new Facade();
        f.method();
    }
}
//外观角色
class Facade
{
    private SubSystem01 obj1=new SubSystem01();
    private SubSystem02 obj2=new SubSystem02();
    private SubSystem03 obj3=new SubSystem03();
    public void method()
    {
        obj1.method1();
        obj2.method2();
        obj3.method3();
    }
}
//子系统角色
class SubSystem01
{
    public  void method1()
    {
        System.out.println("子系统01的method1()被调用!");
    }   
}
//子系统角色
class SubSystem02
{
    public  void method2()
    {
        System.out.println("子系统02的method2()被调用!");
    }   
}
//子系统角色
class SubSystem03
{
    public  void method3()
    {
        System.out.println("子系统03的method3()被调用!");
    }   
}
3.应用场景

1.对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系。
2.当一个复杂系统的子系统很多时,外观模式可以为系统设计一个简单的接口供外界访问。
3.当客户端与多个子系统之间存在很大的联系时,引入外观模式可将它们分离,从而提高子系统的独立性和可移植性。

------行为型模式-------

1.模板方法模式

1.定义与特点

定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。它是一种类行为型模式。
该模式的主要优点如下。
1.它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
2.它在父类中提取了公共的部分代码,便于代码复用。
3.部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。

该模式的主要缺点如下。
1.对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
2.父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。

2.模式的实现
package templateMethod;
public class TemplateMethodPattern
{
    public static void main(String[] args)
    {
        AbstractClass tm=new ConcreteClass();
        tm.TemplateMethod();
    }
}
//抽象类
abstract class AbstractClass
{
    public void TemplateMethod() //模板方法
    {
        SpecificMethod();
        abstractMethod1();          
         abstractMethod2();
    }  
    public void SpecificMethod() //具体方法
    {
        System.out.println("抽象类中的具体方法被调用...");
    }   
    public abstract void abstractMethod1(); //抽象方法1
    public abstract void abstractMethod2(); //抽象方法2
}
//具体子类
class ConcreteClass extends AbstractClass
{
    public void abstractMethod1()
    {
        System.out.println("抽象方法1的实现被调用...");
    }   
    public void abstractMethod2()
    {
        System.out.println("抽象方法2的实现被调用...");
    }
}
3.应用场景

1.算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
2.当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。首先,要识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
3.当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展。

2.策略模式

1.定义与特点

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

2.模式的实现
package strategy;
public class StrategyPattern
{
    public static void main(String[] args)
    {
        Context c=new Context();
        Strategy s=new ConcreteStrategyA();
        c.setStrategy(s);
        c.strategyMethod();
        System.out.println("-----------------");
        s=new ConcreteStrategyB();
        c.setStrategy(s);
        c.strategyMethod();
    }
}
//抽象策略类
interface Strategy
{   
    public void strategyMethod();    //策略方法
}
//具体策略类A
class ConcreteStrategyA implements Strategy
{
    public void strategyMethod()
    {
        System.out.println("具体策略A的策略方法被访问!");
    }
}
//具体策略类B
class ConcreteStrategyB implements Strategy
{
  public void strategyMethod()
  {
      System.out.println("具体策略B的策略方法被访问!");
  }
}
//环境类
class Context
{
    private Strategy strategy;
    public Strategy getStrategy()
    {
        return strategy;
    }
    public void setStrategy(Strategy strategy)
    {
        this.strategy=strategy;
    }
    public void strategyMethod()
    {
        strategy.strategyMethod();
    }
}
3.应用场景
  1. 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
  2. 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
  3. 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
  4. 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构
  5. 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。

3.责任链模式

1.定义与特点

为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
1.增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
2.增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
3.责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
4.责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

2.模式的实现
package chainOfResponsibility;
public class LeaveApprovalTest
{
    public static void main(String[] args)
    {
        //组装责任链 
        Leader teacher1=new ClassAdviser();
        Leader teacher2=new DepartmentHead();
        Leader teacher3=new Dean();
        //Leader teacher4=new DeanOfStudies();
        teacher1.setNext(teacher2);
        teacher2.setNext(teacher3);
        //teacher3.setNext(teacher4);
        //提交请求 
        teacher1.handleRequest(8);
    }
}
//抽象处理者:领导类
abstract class Leader
{
    private Leader next;
    public void setNext(Leader next)
    {
        this.next=next; 
    }
    public Leader getNext()
    { 
        return next; 
    }   
    //处理请求的方法
    public abstract void handleRequest(int LeaveDays);       
}
//具体处理者1:班主任类
class ClassAdviser extends Leader
{
    public void handleRequest(int LeaveDays)
    {
        if(LeaveDays<=2) 
        {
            System.out.println("班主任批准您请假" + LeaveDays + "天。");       
        }
        else
        {
            if(getNext() != null) 
            {
                getNext().handleRequest(LeaveDays);             
            }
            else
            {
                  System.out.println("请假天数太多,没有人批准该假条!");
            }
        } 
    } 
}
//具体处理者2:系主任类
class DepartmentHead extends Leader
{
    public void handleRequest(int LeaveDays)
    {
        if(LeaveDays<=7) 
        {
            System.out.println("系主任批准您请假" + LeaveDays + "天。");       
        }
        else
        {
            if(getNext() != null) 
            {
                  getNext().handleRequest(LeaveDays);             
            }
            else
            {
                System.out.println("请假天数太多,没有人批准该假条!");
           }
        } 
    } 
}
//具体处理者3:院长类
class Dean extends Leader
{
    public void handleRequest(int LeaveDays)
    {
        if(LeaveDays<=10) 
        {
            System.out.println("院长批准您请假" + LeaveDays + "天。");       
        }
        else
        {
              if(getNext() != null) 
            {
                getNext().handleRequest(LeaveDays);             
            }
            else
            {
                  System.out.println("请假天数太多,没有人批准该假条!");
            }
        } 
    } 
}
//具体处理者4:教务处长类
class DeanOfStudies extends Leader
{
    public void handleRequest(int LeaveDays)
    {
        if(LeaveDays<=20) 
        {
            System.out.println("教务处长批准您请假"+LeaveDays+"天。");       
        }
        else
        {
              if(getNext()!=null) 
            {
                getNext().handleRequest(LeaveDays);          
            }
            else
            {
                  System.out.println("请假天数太多,没有人批准该假条!");
            }
        } 
    } 
}
3.应用场景

1.有多个对象可以处理一个请求,哪个对象处理该请求由运行时刻自动确定。
2.可动态指定一组对象处理请求,或添加新的处理者。
3.在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

4.观察者模式

1.定义与特点

指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。

观察者模式是一种对象行为型模式,其主要优点如下。
1.降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
2.目标与观察者之间建立了一套触发机制。

2.模式的实现
package observer;
import java.util.*;
public class RMBrateTest
{
    public static void main(String[] args)
    {
        Rate rate=new RMBrate();         
        Company watcher1=new ImportCompany(); 
        Company watcher2=new ExportCompany();           
        rate.add(watcher1); 
        rate.add(watcher2);           
        rate.change(10);
        rate.change(-9);
    }
}
//抽象目标:汇率
abstract class Rate
{
    protected List<Company> companys=new ArrayList<Company>();   
    //增加观察者方法
    public void add(Company company)
    {
        companys.add(company);
    }    
    //删除观察者方法
    public void remove(Company company)
    {
        companys.remove(company);
    }   
    public abstract void change(int number);
}
//具体目标:人民币汇率
class RMBrate extends Rate 
{
    public void change(int number)
    {       
        for(Company obs:companys)
        {
            ((Company)obs).response(number);
        }       
    }

}
//抽象观察者:公司
interface Company
{
    void response(int number);
}
//具体观察者1:进口公司 
class ImportCompany implements Company 
{
    public void response(int number) 
    {
        if(number>0)
        {
            System.out.println("人民币汇率升值"+number+"个基点,降低了进口产品成本,提升了进口公司利润率。"); 
        }
        else if(number<0)
        {
              System.out.println("人民币汇率贬值"+(-number)+"个基点,提升了进口产品成本,降低了进口公司利润率。"); 
        }
    } 
} 
//具体观察者2:出口公司
class ExportCompany implements Company 
{
    public void response(int number) 
    {
        if(number>0)
        {
            System.out.println("人民币汇率升值"+number+"个基点,降低了出口产品收入,降低了出口公司的销售利润率。"); 
        }
        else if(number<0)
        {
              System.out.println("人民币汇率贬值"+(-number)+"个基点,提升了出口产品收入,提升了出口公司的销售利润率。"); 
        }
    } 
}
3.应用场景

1.对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
2.当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。

4.UML

1.类

类是面向对象系统组织结构的核心,它是对一组具有相同属性、操作、关系和语义的对象的抽象。在 UML 中,类使用带有分隔线的矩形来表示,它包括名称部分(Name)、属性部分(Attribute)和操作部分(Operation)。

其中,属性的表示形式是:[可见性]属性名:类型[=默认值]

操作的表示形式是:[可见性]名称(参数列表)[:返回类型]

注意:“可见性”包括公有(public)、私有(private)、受保护(protected)和朋友(fiiendly)等 4 种,在类图中分别用符号+、-、#、~来表示。

图 3 所示是类的 UML 图形表示方式。


图3 类的UML画法

2.类之间的关系

在软件系统中,类不是孤立存在的,类与类之间存在各种关系。根据类与类之间的耦合度从弱到强排列,有依赖关系、关联关系、聚合关系、组合关系、泛化关系和实现关系等 6 种,它们的功能在UML中的类图及类图之间的关系一文中已经介绍,下面介绍它们在 UML 中的表示方式。
1.依赖关系(Dependency),使用带箭头的虚线来表示,箭头从使用类指向被依赖的类。
2.关联关系(Association),分为双向关联和单向关联两种。其中,双向关联可以用带两个箭头或者没有箭头的实线来表示,单向关联用带一个箭头的实线来表示,箭头从使用类指向被关联的类。还可以在关联线的两端标注角色名,补充说明它们的角色。
3.聚合关系(Aggregation),用带空心菱形的实线来表示,菱形指向整体。
4.组合关系(Composition),用带实心菱形的实线来表示,菱形指向整体。
5.泛化关系(Generalization),用带空心三角箭头的实线来表示,箭头从子类指向父类。
6.实现关系(Realization),用带空心三角箭头的虚线来表示,箭头从实现类指向接口。

图 4 所示是类之间的关系在 UML 中的图形表示方式。


图4 UML中的类的关系图

相关文章

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • 设计模式笔记汇总

    目录 设计原则 “依赖倒置”原则 未完待续... 设计模式 设计模式——策略模式 设计模式——装饰者模式 设计模式...

  • 设计模式

    《C#设计模式》 《C#设计模式》-设计模式概述 《C#设计模式》-面向对象设计原则 《C#设计模式》-单例模式 ...

  • 浅谈JS的一些设计模式

    @(书籍阅读)[JavaScript, 设计模式] 常见设计模式 设计模式简介 设计模式概念解读 设计模式的发展与...

  • 前端设计模式

    JS设计模式一:工厂模式jS设计模式二:单例模式JS设计模式三:模块模式JS设计模式四:代理模式JS设计模式五:职...

  • 设计模式之工厂模式

    设计模式之工厂模式 标签(空格分隔): 设计模式 工厂模式 设计模式的感念 设计模式的应用 工厂设计模式的产生 工...

  • JavaJavascript基础进阶(十七)JS中常用的设计模式

    单利设计模式、构造原型设计模式、发布订阅设计模式、promise设计模式 单利模式 构造原型设计模式 最贴近OOP...

  • 设计模式 - 目录

    设计模式01 - 单例模式 设计模式02 - 工厂模式 设计模式03 - 建造者模式 设计模式04 - 适配器模式...

  • 第1章 设计模式概述

    一、设计模式的概念 二、设计模式的历史 三、设计模式的要素 四、设计模式的分类 ■ 创建型设计模式 ■ 结构型设计...

  • iOS设计模式(3)适配器模式

    设计模式系列文章 《iOS设计模式(1)简单工厂模式》《iOS设计模式(2)工厂模式》《iOS设计模式(4)抽象工...

网友评论

      本文标题:设计模式

      本文链接:https://www.haomeiwen.com/subject/wsrpdktx.html