# 设计模式-analysis

# 深入理解面向对象三大特性之封装

# 引入

之前我看了设计模式,并且自己着手实现了一遍,对于类、抽象类、接口之间的关系和深度有了更多的认识!

然后,这段时间用Java着手实现数据结构中的线性表、树等.

这个过程中一方面自己思考怎么写,另一方面参考Java工具类Util中的Collection,从模仿到抄袭,完成了数据结构的实现.

然后,我感受到了面向对象的魅力!并且,在实现某个类的时候,有种感觉就像在一个世界、一个生态畅游,并发挥自己的想象力,不断完善这个世界!

这个感受,我个人觉得必须要基于以下几个方面.

1. 这个世界【类】是有规则的,什么样的东西能够干什么样的事情必须要明确,就像鱼不能离开水一样,变量也不能离开类型.

2. 这个世界【类】的内部是一个有生命力的城市,它可以不断的扩建,而且在每次建设前都能够被使用. 这就是类的继承和类的版本迭代.

3. 这个世界【类】是有自己的交际桥梁的,如果我们想访问这个世界,就必须通过这个桥梁. 就像类的实例对象和它的方法.

在以上几点的启发下,我们把一个类剥离来重新审视它,就会发现,这个世界【类】的建设是可以沉浸在里面的. 比如一个人的世界【类】

# 我们想在这个世界里创造,先有一个人的基本信息


public class World {

    static class Person{

        private String name;
        private int age;
        private boolean sex;

    }
}

# 然后,这个世界有了一个人


public class World {

    private Person person;

    static class Person{

        private String name;
        private int age;
        private boolean sex;

    }
}

# 后来,这个世界有了一群人


public class World {

    private List<Person> persons;

    static class Person{

        private String name;
        private int age;
        private boolean sex;

    }
}

# 现在,我们跟她们一起建设这个世界.

我想让世界有城市,让所有的人都有家可归


public class World {

    private List<Person> persons;

    static class Person{

        private String name;
        private int age;
        private boolean sex;

    }

    static class City{
        private String cityName;
        private int area;
        private List<Person> peopleInCity;
    }
}

# 这还不够,城市里的人,应该有自己的活动,这种活动是基于人与人之间的关系

public class World {

    private List<Person> persons;

    private Map<String, String> rations;

    static class Person{

        private String name;
        private int age;
        private boolean sex;

    }

    static class City{
        private String cityName;
        private int area;
        private List<Person> peopleInCity;
    }

    public void peopleRation(){
        rations = new HashMap<>();
        this.persons.forEach(e->{
            this.persons.forEach(o->{
                // 存放两个人的关系
                rations.put(e.name,o.name);
            });
        });
    }
}

# 这个世界的城市应该有很多个


public class World {

    private List<Person> persons;

    private Map<String, String> rations;

    private List<City> cities;

    static class Person{

        private String name;
        private int age;
        private boolean sex;

    }

    static class City{
        private String cityName;
        private int area;
        private List<Person> peopleInCity;
    }

    public void peopleRation(){
        rations = new HashMap<>();
        this.persons.forEach(e->{
            this.persons.forEach(o->{
                // 存放两个人的关系
                rations.put(e.name,o.name);
            });
        });
    }
}

# 我们要建设我们的城市,我们要结合生育新生儿

public class World {

    private List<Person> persons = new LinkedList<>();

    private Map<String, String> rations;

    private List<City> cities = new LinkedList<>();

    static class Person{
        private String name;
        private int age;
        private boolean sex;
        Person(String name,int age ,boolean sex){
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    }

    static class City{
        private String cityName;
        private int area;
        private List<Person> peopleInCity;
        City(String cityName,int area){
            this.cityName = cityName;
            this.area = area;
        }
    }

    public void peopleRation(){
        rations = new HashMap<>();
        this.persons.forEach(e->{
            this.persons.forEach(o->{
                // 存放两个人的关系
                rations.put(e.name,o.name);
            });
        });
    }

    public void buildCity(String cityName,int area){
        cities.add(new City(cityName,area));
    }

    public void bearPerson(String name,int age ,boolean sex){
        persons.add(new Person(name, age, sex));
    }
    }

就这样,这个世界不断的被完善. 我们沉浸在自己的世界中建设.

这就是封装. 自成世界,自有生态!

# 学设计模式的意义

# 为什么要学设计模式?

对于设计模式学习的必要性:个人的学习体会,初学编程者,不要学. 什么样的人适合学习它? 有实际生产经验的小伙伴.

带着实际生产过程中的问题和对代码使用的熟练度来学习设计模式,学得更快、理解得更深、明白的透彻. 否则,可能会越学越糊涂.

至于学习它的必要性,强制学. 这是我们能够读懂源码****的基础. 是未来天花板有多高的基础. 也是编程路上能够远行的核心之一.

# 随心所欲的编程

类是一种思想,是一种模型. 现实中所有的事物都能够被它表示,无论真实的还是抽象的. 并用计算机能够明白的方式,让它呈现.

OOP,面向对象编程的方式,让类的作用更加伟大. 为什么是伟大?**你见过世界上有什么样的数学模型是能够表达所有事物吗? **NO. 但类做到了.

接口是一种思想,是一种模式. 现实或虚拟中所有的规则都能够被它表示,它的规则依赖类的表达. 是对OOP的延申.

类和接口的关系,就像鱼和水,现实和虚拟,阳和阴. 它们在一起就是完整的. 它们的结合,让世界上现实的事物和虚拟的规则都得以实现,因此,计算机被它们构建. 能够变成一个真实世界的映射. 这些的实现可以称之为伟大.掌握了它们表达世界的法则,就掌握了随心所欲编程的奥秘.

# 设计模式的核心

如果你去回顾所有的设计模式,就会发现这些法则,因为所有的设计模式,并没有用到多么高级技术. 它们只有一套. 这一套包括以下一些规则:

【继承】:extend,这个规则,让类之间有不用调用就存在的通道,就像亲戚和陌生人之间的关系一样,继承了一个类,就继承了这个类的所有.

【实现】:implements,这个规则,给类的行为一些约束,类的执行看它的约束,就像颁布的法令,需要人去执行一样. 实现只存在于接口和类之间.

【规则】:其他的类似于 类的成员变量、类的构造方法、类的调用和类的生产,都是很基础的知识.

以上,都是很基础的知识. 设计模式就是在这些的基础上,把编码玩出了花.

但是看完设计模式,你会发现,所有的模式都用一套方案解决一些共性的问题,比如耦合性,灵活度等.

# 关于类的职能

【单一职能】:一个类只解决一个问题

【类有规范】:不管多大的项目,多简单的项目,类都在接口的规范下设计,也就是先有接口,后有类

【自顶向下】:所有的解决方案都是从解决一类问题开始,再通过类的单一功能实现问题的细分和解决.

【模块化的】:类之间的关系通过模块化的方式去设计

【可开放性】:封闭性就是类是否向外开放,一个开放的类具有get方法,不开放的类不给get方法,如果对类的开放程度有要求,可以在get方法里面写一些约束.

【高端调用】:在进行类的使用的时候,如果有接口,就通过接口调用,而不直接让类之间产生耦合

【面向问题】:所有的设计模式都是面向问题的解决方案,如空对象模式解决空对象问题,享元模式解决资源浪费问题,过滤器模式解决约束问题

# 从设计模式看类和接口

# 1.接口的能力


接口:我是一个接口,我的诞生是一个跨越式的进步. 因为我有很多能力,完善计算机的漏洞,让编程变得更加高效. 以下是我的能力清单.

# 【管理类的能力】

我是如何管理类的呢?凡是实现了我的类都需要遵循我的规则,重新实现自己的方法. 我能够管理的类,都是有相同特征的类,一个接口只负责一个能力. 被我管理的类就只有这一个能力.

//我是一个接口,我的能力是计算策略,实现了我的类都具备计算的能力
1public interface Strategy {
   public int doOperation(int num1, int num2);
}
//我是一个类,我实现了上面的接口,我具有加法计算的能力
public class OperationAdd implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 + num2;
   }
}
//我是一个类,我实现了上面的接口,我具有减法计算的能力
public class OperationSubtract implements Strategy{
   @Override
   public int doOperation(int num1, int num2) {
      return num1 - num2;
   }
}
# 【分身术的能力】

什么是我的分身术呢?我是一个接口,我的一天很繁忙. 需要做的事情很多,因为我是一个接口,我是抽象的虚拟的,只要我不断的分化自己,产生新的不一样的我,让它们替我工作,就有无数个我. 在需要某个具体的事时,我只要找到那个具体的我就好了. 我的这些分身被称为类.

//我是一个接口,我有很多工作,比如画图形的工作,很多时候我都忙不过来,这时候我就会创造一些分身,让它们去画
public interface Shape {
   void draw();
}
//我是一个画矩形的类,是上面的接口创造的我,我是它的分身之一,我只负责画矩形
public class Rectangle implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Rectangle::draw() method.");
   }
}
//我是一个画正方形的类,是上面的接口创造的我,我是它的分身之一,我只负责画正方形
public class Square implements Shape {
 
   @Override
   public void draw() {
      System.out.println("Inside Square::draw() method.");
   }
}
# 【附身术的能力】

我是一个接口,我有一个分身术的能力,只要我愿意,我可以是分身中的任何一个. 因为分身是我自己,我想成为任何一个分身都可以.

//使用 getShape 方法实现接口的附身术
//Shape:这就是我,不管它们是谁,最终都是我
   public Shape getShape(String shapeType){
      if(shapeType == null){
         return null;
      }
      if(shapeType.equalsIgnoreCase("CIRCLE")){
         return new Circle();
      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){
         return new Rectangle();
      } else if(shapeType.equalsIgnoreCase("SQUARE")){
         return new Square();
      }
      return null;
   }
# 【隐身术的能力】

我是一个接口,我有一个分身术的能力,只要我愿意,我可以是分身中的任何一个. 我还有附身术的能力,可以随时成为分身中的任意一个. 因为我的这两个能力,没有人知道哪个才是真的我.

ShapeFactory shapeFactory = new ShapeFactory();
 
      //获取 Circle 的对象,并调用它的 draw 方法
      Shape shape1 = shapeFactory.getShape("CIRCLE");
 
      //调用 Circle 的 draw 方法
      shape1.draw();
 
      //获取 Rectangle 的对象,并调用它的 draw 方法
      Shape shape2 = shapeFactory.getShape("RECTANGLE");
 
      //调用 Rectangle 的 draw 方法
      shape2.draw();
 
      //获取 Square 的对象,并调用它的 draw 方法
      Shape shape3 = shapeFactory.getShape("SQUARE");
 
      //调用 Square 的 draw 方法
      shape3.draw();

# 2.类的规则


类:我是一个类,我的诞生是一个里程碑的进步. 因为我的能力,世界万物皆可被建模. 以下是我的能力清单.

# 【模仿抽象的能力】

我是一个类,我可以模仿世间万物. 因为我有两个神器:属性和方法. 它们可以用来抽象所有的事物.

//我是一个类,用来抽象一个人
@Data
public class People{
//这些是我的属性,用来描述这个人的特征
private int age;
private string name;
private string sex;
private string shenggao;
......

//这些是我的方法,用来描述这个人的行为特征
public void eat(){

}
.......

}
# 【自我保护的能力】

我是一个类,我可以模仿世间万物. 因为我有两个神器:属性和方法. 它们可以用来抽象所有的事物. 我也可以选择保护自己,让自己不被发现,这取决于我自己的想法.

//我是一个钱的类,我可以选择性的让别人知道我是不是有很多钱
public class money{

private int money;

//我可以知道你的秘密
public void setMoney(int money){
this.money = money;
}

//我可以选择性的让你知道我的秘密
public int getMoney(Object object){
 if(object){
    return something;
    }
 return this.money;
    }
}
# 【生产对象的能力】

我是一个类,我可以模仿世间万物. 因为我有两个神器:属性和方法. 它们可以用来抽象所有的事物. 但是我仅仅是一个模板,如果要得到一个具体的事物,就需要生产,生产的具体事物是对象. new 是我生产对象的神器.

People people = new People();