课时93:案例分析二(绘图处理)

简介: 本文介绍了绘图系统的基本原理和实操示例。通过定义绘图标准接口(如 `IGraphical`),客户端无需关心具体图形的实现细节,只需调用绘制方法。具体图形类(如圆形、三角形)实现该接口,完成各自的绘制逻辑。工厂类负责创建不同类型的图形对象,简化了客户端代码。示例展示了如何使用工厂模式创建并绘制三角形和圆形,强调了设计模式在绘图系统中的应用。

课时93:案例分析二(绘图处理)

摘要:

1.基本原理

2.绘制实例

 

01. 绘制的基本原理

 

设计一个绘图系统,使其能够根据不同的图形类型进行绘制。这实际上是一个设计过程,理解这个过程至关重要。


考虑一个现实场景:绘图。一个典型的绘图程序通常包含以下几个关键部分:

1. 客户端(Client):客户端主要关注图形的绘制标准,它并不需要了解具体的图形实现细节。


2.  绘图标准(Drawing Standard/Interface):这是一个抽象层,定义了绘图的基本行为。例如, Drawable  接口可以定义一个  draw()  方法。


3.具体图形(Concrete Shapes):客户端可以通过绘图标准创建各种图形,如圆形、三角形和矩形。这些图形都实现了绘图标准。


这样的程序通常可以分解为几个主要部分。

首先,需要定义一个标准,或者说接口。客户端无需关心具体的实现细节,它主要关注的是图形绘制的标准。这个标准定义了绘图的基本行为,例如,如何绘制一个图形。基于这个绘图标准,可以创建各种具体的图形类,比如圆形、三角形和矩形等。


每种图形都遵循绘图标准,实现自己的绘制方式。例如,使用某个绘图软件,你会发现各种图形工具的功能基本相同,只是操作的形式和绘制的形状不同。


然而,从另一个角度来看,客户端代码实际上并不需要知道要绘制的是什么具体的形状。客户端更关心的是如何获取绘图对象,并使用绘图工具类来实现图形的绘制。至于有多少种图形类型,客户端并不需要关心。图形绘制类负责将图形输出到不同的媒介,例如文本文件。


整个代码的设计流程强调的是一种抽象,即客户端不需要了解具体的绘制实现。客户端只需要按照标准获取绘图对象,并调用相应的绘制方法。


在这种设计模式下,可以引入一个工厂类(Factory)来负责创建具体的图形对象。客户端与工厂交互,工厂再与具体的图形子类关联。同时,工厂也需要与绘图标准接口关联。


这种设计方式能够清晰地描述出程序的基本结构。这种设计思想就是所谓的标准定义与实现分离。如果需要定义绘图标准,应该采用这种结构。

 

image.png

 

02. 绘制实操

 

interface IGraphical { //定义绘图标准
    public void paint();
}
class Point{ //坐标的点,点有 x , y 两个数值
    private double x;
    private double y;
    public Point(double x,double y){
        this.x=x;
        this.y=y;
    }
    public double getY {
        return this.y;
    }
    public double getX {
        return this.x;
    }
}
class Triangle<p> implements IGraphical {//绘制三角形
    private Point[] x;// 保存第一条边的坐标
    private Point[] y;//保存第二条边的坐标
    private Point[] z;// 保存第三条边的坐标,坐标必须提供且长度正确
    public Triangle ( double[] x, double[] y, double[] z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    public void paint(){
        // 打印绘制第一条边的开始坐标和结束坐标
        public void paint(){
            // 打印绘制第一条边的开始坐标和结束坐标
     System.out.println("绘制第一条边,开始坐标:["+this.x[0].getX()+","+this.y[0].getY()+"],结束坐标:["+this.x[1].getX()+","+this.y[1].getY()+"]");
            //打印绘制第二条边的开始坐标和结束坐标
     System.out.println("绘制第一条边,开始坐标:["+this.y[0].getX()+","+this.z[0].getY()+"],结束坐标:["+this.y[1].getX()+","+this.z[1].getY()+"]");
            //打印绘制第三条边的开始坐标和结束坐标
     System.out.println("绘制第一条边,开始坐标:["+this.x[0].getX()+","+this.z[0].getY()+"],结束坐标:["+this.x[1].getX()+","+this.z[1].getY()+"]");
        }
    }
// 定义一个名为圆形的类
class Circular implements IGraphical{
    class Circular implements IGraphical {
        private double radius; //设置半径
        public Circular(double radius) {
            this.radius = radius;
        }
        public void paint() { //设置绘图,以半径进行绘制
            System.out.println("以半径为" + this.radius + "绘制圆形。");
        }
    }
}
}
class Factory {
    public static IGraphical getInstance(String className, double... args) {  
        if(" triangle".equalsIgnoreCase(className)) { //给三角形实例
            return new Triang1e(
                    new Point[]{
                            new Point(args [ 0 ] ,args [ 1 ] ), new Point(args [ 2 ] ,args[3]}  //进行封装,第一组,x ,y 的坐标
        new Point[]{
           new Point(args [ 4 ] ,args [ 5 ] ), new Point(args [ 6 ] ,args[7]}
//第二组的坐标,y ,z 的坐标
       new Point[]{
            new Point(args [ 8 ] ,args [ 9 ] ), new Point(args [ 10 ] ,args[11]}
                    );//第三组的坐标,x, z 的坐标
        } else if ("circle".equalsIgnoreCase(className)) //给圆形,只用给半径
            return  new Circu1ar (args [ 0 ] )
    }else{
        return null;
    }
}
}
public class JavaDemo {
    public static void main (String args [ ]) {
IGraphical
iga =Factory.getInstance(("triangle",1.1,2.2,3.3,11.11,22.22,33.33,111.111,222.222,333.333));
iga.paint(); //绘制三角
    }

输入  javac JavaDemo.java  进行编译

输入  java JavaDemo 执行运行结构如下:

image.png

进行圆形的绘制:

public class JavaDemo {
public static void main (String args [ ]) {
IGraphical  iga =Factory.getInstance(("triangle",1.1,2.2,3.3,11.11,22.22,33.33,111.111,222.222,333.333));
iga.paint(); //绘制三角
Graphical 
igb=Factory.getInstance(("circular",88.11));
igb.paint(); //绘制圆形


再次编译执行,结果如下:

image.png

注:

image.png

三角形需要三边, x ,y , z

这样就描述了一个基本的绘图系统结构。需要注意的是,这里的代码仅仅是示例,用于演示设计思想,并没有实现真正的绘图功能。这个例子主要目的是为了展示设计模式的应用。

 

相关文章
|
7月前
|
设计模式 Java 开发者
课时92:案例分析一(获取类信息)
本文通过具体的Java开发案例,深入讲解抽象类与接口的相关知识,旨在巩固概念,引导读者深入思考,并掌握接口在实际编程中的应用,同时强调代码编写规范。 在Java编程中,抽象类与接口是极为核心的概念,它们也是众多设计模式的综合体现。在后续的学习过程中,开发者会频繁接触到系统提供的接口和抽象类。 因此,深入理解并巩固这些概念至关重要。在接口与抽象类都可使用的情况下,应优先选用接口,这是因为接口能有效避免单继承的局限性。接下来,将通过实际案例对相关概念进行分析。
|
JSON 自然语言处理 数据格式
DSL语法
DSL语法
268 0
|
机器学习/深度学习 数据采集 数据可视化
使用Python实现深度学习模型:智能舆情监测与分析
【8月更文挑战第16天】 使用Python实现深度学习模型:智能舆情监测与分析
845 1
|
11月前
|
存储 SQL 关系型数据库
MySQL创建表
如何使用MySQL CREATE TABLE语句在数据库中创建新表。
278 0
|
存储 索引 Python
从中序与后序遍历序列构造二叉树
【10月更文挑战第13天】这段内容介绍了一种基于中序和后序遍历序列构建二叉树的方法。通过识别后序遍历中的根节点,并利用中序遍历划分左右子树,进而递归构建整棵树。文中提供了具体示例及Python代码实现,并分析了该方法的时间与空间复杂度。
331 0
|
11月前
|
机器学习/深度学习 数据采集 数据挖掘
解锁 Python 数据分析新境界:Pandas 与 NumPy 高级技巧深度剖析
Pandas 和 NumPy 是 Python 中不可或缺的数据处理和分析工具。本文通过实际案例深入剖析了 Pandas 的数据清洗、NumPy 的数组运算、结合两者进行数据分析和特征工程,以及 Pandas 的时间序列处理功能。这些高级技巧能够帮助我们更高效、准确地处理和分析数据,为决策提供支持。
235 2
|
前端开发 JavaScript Java
Python错误、异常和模块
本文详细介绍了Python编程中的错误和异常处理以及模块的使用方法。语法错误如遗漏引号会导致`SyntaxError`,而运行时错误如除以零则会产生`ZeroDivisionError`等异常。文章通过实例展示了如何使用`try...except`结构来捕获并处理异常,确保程序的健壮性。此外,还介绍了如何自定义异常以及主动抛出异常的方法。在模块方面,文章解释了如何创建和导入模块以重用代码,并展示了不同导入方式的特点,包括导入单个函数、全部内容等。最后提到了Python标准库的使用和查询模块内容的方法。
215 0
|
人工智能 算法 大数据
探究操作系统的心脏:调度算法的进化与影响
本文深入探讨了操作系统中核心组件——调度算法的发展及其对系统性能的影响。通过分析先来先服务、短作业优先、时间片轮转等传统调度算法,阐述了它们的原理和优缺点。同时,讨论了现代调度算法如多级队列和优先级调度在提高系统响应速度和处理能力方面的作用。文章还探讨了实时系统中的调度挑战,以及如何通过优化调度策略来满足不同应用场景下的性能需求。
|
Linux 编译器 C语言
深入理解Linux中的`as`命令:汇编器之旅
`as`命令是Linux下的GNU汇编器,用于将汇编语言源码(.s或.S)转化为机器码目标文件(.o)。它是GNU Binutils的一部分,在编译流程中扮演重要角色,尤其在底层编程和硬件交互时。基本用法是`as -o outputfile inputfile`。选项如`-g`添加调试信息,`-I`指定包含文件路径。通常与编译器如`gcc`配合使用,提供对计算机工作原理和操作系统底层的深入理解。学习汇编语言能增强编程和系统理解能力。
|
Linux 数据安全/隐私保护
在Linux中,如何进行文件系统的迁移和升级?
在Linux中,如何进行文件系统的迁移和升级?