初识设计模式

2016-10-03  本文已影响0人  Dddddw

每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心.这样,你就能一次又一次地使用该方法而不必做重复劳动
by Christopher Alexander

从目前的编码过程中,可能我的状态就是比较注重功能的实现,然而面对其他的比如对象之间的耦合关系什么的基本没有考虑到,虽然使用着面向对象的语言,做的好像不是面向对象的事情。学习设计模式能让人加深对面向对象编程的理解,有时候会让人有一种醍醐灌顶的感觉。然而设计模式虽好,但不要沉迷其中无法自拔,还是得有自己的思考。好了说了些废话,正文开始了。

说到设计模式就不得不提一本书GOF设计模式:可复用面向对象软件的基础,我们把目光锁定在后面的解释,可复用,正如开头所引用的话,模式的最终目标就是复用,放在软件开发中也是如此,一个臃肿的类体系是人们不愿意看到的。另外,设计模式提供了一种不同的思维方式,它使得我们跳出了事物本身的局限,去考虑更加本质的东西,首先就从java的面向对象说起,这里有两种不同的思维方式

抽象思维是建立在比较升入理解了底层思维的基础上的,面向对象的三大特性:封装(隐藏内部实现),继承(复用现有代码),多态(改写对象行为),这三大特性在设计模式里十分重要,在设计模式里,理解灵活多变的利用这三大特性来描述现实世界,也就理解了设计模式这样设计的原因和意义所在。

由于个人水平比较菜,所以现在也还没有参与过什么项目,然而耳闻过。为什么说软件设计很复杂,因为在项目开展的过程中,会有永运猜不透想法的客户的需求变化,你不得不接受的团队成员的流动,技术平台日新月异的更新等一系列不可控因素,然而在软件设计的初期要尽可能的把这些变化考虑进去,难不难,当然难。需不需要去解决,当然需要!怎么解决?当人们遇到比较复杂的问题的时候,都这样做,我也这样做:

比如我们有两个图形类:

//直线类
class Line {
    public int startX;
    public int startY;
    public int endX;
    public int endY;

    public Line(int startX, int startY, int endX, int endY) {
        this.startX = startX;
        this.startY = startY;
        this.endX = endX;
        this.endY = endY;
    }
}

//矩形类
class Rect {
    public int left;
    public int top;
    public int right;
    public int bottom;

    public Rect(int left, int top, int right, int bottom) {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }
}

然后在MainActivity中分别实现,不需要在意功能,就只关心使用的地方

  Vector<Line> lineVector = new Vector<Line>();
  Vector<Rect> rectVector = new Vector<Rect>();

     if (lineRadio.isChecked()) {
                    lineVector.add(new Line(startPoint.x,
                            startPoint.y,
                            endPoint.x,
                            endPoint.y));
                } else if (rectRadio.isChecked()) {
                    rectVector.add(new Rect(startPoint.x,
                            startPoint.y,
                            endPoint.x,
                            endPoint.y));
                }
                //更改...
                else if(...){

                }
          }
            for (int i = 0; i < lineVector.size(); i++) {

                canvas.drawLine(lineVector.get(i).startX,
                        lineVector.get(i).startY,
                        lineVector.get(i).endX,
                        lineVector.get(i).endY,
                        paint);
            }

            for (int i = 0; i < rectVector.size(); i++) {

                canvas.drawRect(rectVector.get(i).left,
                        rectVector.get(i).top,
                        rectVector.get(i).right,
                        rectVector.get(i).bottom,
                        paint);

            }

上面第一段代码是先生成每一个图形的Vector,然后分别add,下面的for循环可以理解为轮询每一个不同的Vector对象,然后画出图形。当代码写完了,突然想起,哎呀忘记Circle了,于是首先得在写出一个Circle的类,然后new一个Circle的Vector数组,接着在add处也要修改,最后还要增加一个for循环,忘记一个就要更改4处,是不是很复杂,而且当代码多的时候,更改的出错率会增多,这是很危险的。
如果我们从另外一方面,或者说抽象出来,这些都是属于图形,那我们定义一个抽象图形类:

//形状基类
abstract class  Shape {

    abstract void draw(Canvas canvas, Paint paint);

}

然其他无论什么图形都继承它。接着生成了一个Vector数组:

Vector<Shape> shapeVector = new Vector<Shape>();

而add时,增加具体图形的数据,for循环也是它,这样不管是什么图形,都可以绘制出来,不用单独去考虑:

      for (int i = 0; i < shapeVector.size(); i++) {

                shapeVector.get(i).draw(canvas, paint);

            }

如果需求变更了,增加了图形,我们只需要继承Shape写一个实体类,再在add处增加新图形的add方法,其他的都不会变化。相对于第一种,当需求变化发生的时候,很多的代码得以复用,而不用像第一种手忙脚乱,这里那里修改,所以相对于分解思维模式,抽象模式的优势就体现出来--复用。

所以用了java语言,并不一定拥有了抽象的设计思维,说的就是我。

重新认识面向对象:

面向对象设计原则:

  1. 依赖倒置原则(DIP)
  1. 开放封闭原则(OCP)
  1. 单一职责原则(SRP)
  1. Liskov替换原则(LSP)
  1. 接口隔离原则(ISP)
  1. 优先使用对象组合,而不是类继承
  1. 封装变化点
  1. 针对接口编程,而不是针对实现编程

老师举了两个例子,一个是秦统一六国之后,统一货币统一度量衡,从软件开发的角度来说就是统一了接口,并且使其规范化。再一个是毕升的活字印刷术,它的发明之所以推进了人类文明的发展,是因为首先复用了每个汉字,按需所用,不需要像雕版印刷一样来一篇文章刻一次版,其次规定了每个字模的大小规格,毕升就是松耦合大师。通过这个感性的认识,就会体会到接口规范化对于行业的贡献。

以上,欢迎指正。

上一篇 下一篇

猜你喜欢

热点阅读