You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
476 lines
8.7 KiB
476 lines
8.7 KiB
|
3 years ago
|
设计模式
|
||
|
|
|
||
|
|
单利设计模式
|
||
|
|
|
||
|
|
格式:
|
||
|
|
|
||
|
|
| 类名 | Simple Class |
|
||
|
|
| ------------------ | ------------ |
|
||
|
|
| 私有量 | \__init__ |
|
||
|
|
| 私有名 | simpleClass |
|
||
|
|
| 公有名(量、方法) | S_object |
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
懒汉模式(lazy Model)
|
||
|
|
|
||
|
|
格式:
|
||
|
|
|
||
|
|
```java
|
||
|
|
class LazyModel{
|
||
|
|
private static lazyModel instance;
|
||
|
|
private LazyModel(){}
|
||
|
|
|
||
|
|
public static LazyModel getInstance(){
|
||
|
|
if (null == instance){
|
||
|
|
synchronized (LazyModel.class){
|
||
|
|
if(null == instance){
|
||
|
|
instance =new LazyModel();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
开闭原则:
|
||
|
|
|
||
|
|
该原则表达的意思在原有的代码上不改变代码,而进行项目的扩展额外的业务或功能。
|
||
|
|
|
||
|
|
例如:
|
||
|
|
|
||
|
|
```java
|
||
|
|
class bookStore {}
|
||
|
|
|
||
|
|
bookStore 类调用 接口Book 的方法,来获得数据。
|
||
|
|
|
||
|
|
NovelBook 子类则是返回处理过的Book类实体。
|
||
|
|
|
||
|
|
当要对书的价格进行一个打折。我们可以重新将NovelBook类进行封装成一个新的子类。
|
||
|
|
通过该子类对NovelBook类里面的价格进行重写覆盖。从而达到一个打折的效果。
|
||
|
|
|
||
|
|
bookStore类就可以获得到打折后的价钱了。
|
||
|
|
```
|
||
|
|
|
||
|
|
这就是开闭原则的概念所表达的意思。
|
||
|
|
|
||
|
|
这原则所带来的好处是,可以保持代码的纯洁性,提高系统的稳定性。缺点是,需要在相应的高层代码中去修改部分改变来适应新的变化。
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
依赖倒置原则:
|
||
|
|
|
||
|
|
所表达的意思为,某个讲某物,但某人无需关注某物的内容类型,直接讲述即可。
|
||
|
|
|
||
|
|
例如:
|
||
|
|
|
||
|
|
```java
|
||
|
|
class StoreBook(){
|
||
|
|
public String getContent()
|
||
|
|
}
|
||
|
|
|
||
|
|
class JOJO {
|
||
|
|
narrate(Book)
|
||
|
|
}
|
||
|
|
|
||
|
|
上述的代码中,JOJO通过narrate的方式来读取Book的内容,并讲述出来。
|
||
|
|
这里所表达的是JOJO对Store Book的关系。
|
||
|
|
|
||
|
|
需求》让JOJO读取任何类型的📚书籍时,我们需要将书籍进行一个抽象化。
|
||
|
|
|
||
|
|
优化方案:
|
||
|
|
public interface ReadingMaterial {
|
||
|
|
void getContent()
|
||
|
|
}
|
||
|
|
|
||
|
|
class storeBook(){
|
||
|
|
private String content;
|
||
|
|
return New storeBook()
|
||
|
|
}
|
||
|
|
|
||
|
|
class JOJO() implements ReadingMaterial{
|
||
|
|
narrate(book.getContent())
|
||
|
|
}
|
||
|
|
|
||
|
|
```
|
||
|
|
|
||
|
|
这样的好处是降低类之间的耦合性,提高系统的稳定性,降低修改系统程序所造成的风险。
|
||
|
|
|
||
|
|
在开发中,这样的设计可使得开发人员之间不需要等待所依赖的类编码完后进行二次开发。
|
||
|
|
|
||
|
|
达到一个同时开发的效果。
|
||
|
|
|
||
|
|
流行的TDD(Test Drive Development)开发模式就是采用这样的原则来开发的。
|
||
|
|
|
||
|
|
示例:
|
||
|
|
|
||
|
|
```java
|
||
|
|
public interface Drive {
|
||
|
|
void drive(PrivateCard card)
|
||
|
|
}
|
||
|
|
|
||
|
|
public interface PrivateCard{
|
||
|
|
void run()
|
||
|
|
}
|
||
|
|
|
||
|
|
class ConereteDriver() implements Drive{
|
||
|
|
@Orriver
|
||
|
|
public void drive(){
|
||
|
|
....
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class BMW () implements PrivateCard{
|
||
|
|
@Orrvier
|
||
|
|
public void run(){
|
||
|
|
....
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class Benz() implements PrivateCard{
|
||
|
|
@Orriver
|
||
|
|
public void run(){
|
||
|
|
....
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
这里的代码同样也是采用依赖倒置原则。
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
接口隔离原则:
|
||
|
|
|
||
|
|
所表达的意思是将某个的操作权限划分为多个角色。为了角色之间不相互影响。所诞生的原则。
|
||
|
|
|
||
|
|
类所依赖的是接口,而不是继承或多态的形式。
|
||
|
|
|
||
|
|
概念:
|
||
|
|
|
||
|
|
类间的依赖关系应建立在接口上。
|
||
|
|
|
||
|
|
客户端不应该依赖它不需要的接口。
|
||
|
|
|
||
|
|
一个接口代表一个角色。我们做的是不强迫角色使用它不用的方法。
|
||
|
|
|
||
|
|
示例:
|
||
|
|
|
||
|
|
```java
|
||
|
|
class Portal () implements PortalInter{
|
||
|
|
@Override
|
||
|
|
public void fnc1();
|
||
|
|
@Override
|
||
|
|
public void fnc2();
|
||
|
|
}
|
||
|
|
|
||
|
|
class OtherSys() implements OtherSysInter{
|
||
|
|
@Override
|
||
|
|
void fnc1();
|
||
|
|
@Override
|
||
|
|
void fnc2();
|
||
|
|
@Override
|
||
|
|
void fnc3();
|
||
|
|
}
|
||
|
|
|
||
|
|
class Admin(){
|
||
|
|
@Override
|
||
|
|
void fnc1():
|
||
|
|
@Override
|
||
|
|
void fnc2();
|
||
|
|
@Override
|
||
|
|
void fnc3();
|
||
|
|
@Override
|
||
|
|
void fnc4();
|
||
|
|
}
|
||
|
|
|
||
|
|
interface PortalInter{
|
||
|
|
void fnc1();
|
||
|
|
void fnc2();
|
||
|
|
}
|
||
|
|
|
||
|
|
interface OtherSysInter{
|
||
|
|
void fnc1();
|
||
|
|
void fnc2();
|
||
|
|
void fnc3();
|
||
|
|
}
|
||
|
|
|
||
|
|
interface Admin {
|
||
|
|
void fnc1():
|
||
|
|
void fnc2();
|
||
|
|
void fnc3();
|
||
|
|
void fnc4();
|
||
|
|
}
|
||
|
|
|
||
|
|
class Order(){
|
||
|
|
void fnc1();
|
||
|
|
void fnc2();
|
||
|
|
void fnc3():
|
||
|
|
void fnc4():
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
上面的代码就是采用了接口隔离原则所实现的。
|
||
|
|
|
||
|
|
好处是可以隔离,缺点是接口的适度性难以控制,需要花费大量时间。
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
迪米特法则:(又称为最少知识原则)
|
||
|
|
|
||
|
|
定义:一个对象应对其他对象有最少了解。
|
||
|
|
|
||
|
|
如果要两个类之间要调用则要通过第三者进行一个转发。
|
||
|
|
|
||
|
|
示例:总公司和分公司之间的关系
|
||
|
|
|
||
|
|
```java
|
||
|
|
优化前:
|
||
|
|
class CompanyManager(){
|
||
|
|
|
||
|
|
}
|
||
|
|
class Employee() extends CompanyManagter{
|
||
|
|
private Integer Id;
|
||
|
|
void getId();
|
||
|
|
void setId(String id);
|
||
|
|
}
|
||
|
|
|
||
|
|
class SubCompanyManager(){
|
||
|
|
|
||
|
|
}
|
||
|
|
class SubEmployee() extends SubCompanyManager{
|
||
|
|
private Integer Id;
|
||
|
|
void subGetId();
|
||
|
|
void subSetId(String id);
|
||
|
|
}
|
||
|
|
|
||
|
|
优化后:
|
||
|
|
class CompanyManager(){
|
||
|
|
List<Employee> getAllEmployee();
|
||
|
|
void printAllEmployee(SubCompanyMaanger subCompanyManager)
|
||
|
|
}
|
||
|
|
class Employee() extends CompanyManagter{
|
||
|
|
private Integer Id;
|
||
|
|
void getId();
|
||
|
|
void setId(String id);
|
||
|
|
}
|
||
|
|
|
||
|
|
class SubCompanyManager(){
|
||
|
|
List<SubEmployee> getAllEmployee();
|
||
|
|
void printAllEmployee()
|
||
|
|
}
|
||
|
|
class SubEmployee() extends SubCompanyManager{
|
||
|
|
private Integer Id;
|
||
|
|
void subGetId();
|
||
|
|
void subSetId(String id);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
这样就可以减少总公司对分公司的处理。
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
合成/聚合复用原则:
|
||
|
|
|
||
|
|
所表达意思是
|
||
|
|
|
||
|
|
示例:汽车选择
|
||
|
|
|
||
|
|
```java
|
||
|
|
思路:
|
||
|
|
采用组合或聚合复用方式,第一步先将将颜色Color抽象为接口,有白色,黑色,红色三个颜色实现类,第二步将Color对象组合在汽车Car类中,最终我们只需要生成5个类,就可以实现上诉功能。同时当增加新的“动力源”或者增加新的“颜色,都不要修改源代码,只要增加实现类就可以。
|
||
|
|
|
||
|
|
public abstract class Car
|
||
|
|
{
|
||
|
|
abstract void run();
|
||
|
|
Color color;
|
||
|
|
public Color getColor() {
|
||
|
|
return color;
|
||
|
|
}
|
||
|
|
public void setColor(Color color) {
|
||
|
|
this.color = color;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public interface Color
|
||
|
|
{
|
||
|
|
void colorKind();
|
||
|
|
}
|
||
|
|
|
||
|
|
public class ElectricCar extends Car
|
||
|
|
{
|
||
|
|
|
||
|
|
@Override
|
||
|
|
void run()
|
||
|
|
{
|
||
|
|
System.out.println("电动汽车");
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public class PetrolCar extends Car {
|
||
|
|
|
||
|
|
@Override
|
||
|
|
void run()
|
||
|
|
{
|
||
|
|
System.out.println("汽油汽车");
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public class White implements Color{
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void colorKind()
|
||
|
|
{
|
||
|
|
System.out.println("白色");
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public class Black implements Color{
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void colorKind()
|
||
|
|
{
|
||
|
|
System.out.println("黑色");
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public class Red implements Color{
|
||
|
|
|
||
|
|
@Override
|
||
|
|
public void colorKind()
|
||
|
|
{
|
||
|
|
System.out.println("红色");
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
public class Test
|
||
|
|
{
|
||
|
|
public static void main(String[] args)
|
||
|
|
{
|
||
|
|
ElectricCar electricCar = new ElectricCar();
|
||
|
|
White color = new White();
|
||
|
|
electricCar.setColor(color);
|
||
|
|
electricCar.getColor().colorKind();//白色
|
||
|
|
electricCar.run();//电动汽车
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
这就是通过合成/复用原则所提供的解决方案。
|
||
|
|
|
||
|
|
----
|
||
|
|
|
||
|
|
类之间的关系:【额外知识】
|
||
|
|
|
||
|
|
依赖关系:
|
||
|
|
|
||
|
|
```java
|
||
|
|
public class Train{
|
||
|
|
public void move(){}
|
||
|
|
}
|
||
|
|
public class Person{
|
||
|
|
public void move(Train train){
|
||
|
|
train.move();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
聚合关系:
|
||
|
|
|
||
|
|
```java
|
||
|
|
public class Engine{}
|
||
|
|
public class Car{
|
||
|
|
private Engine engine;
|
||
|
|
public Car(Engine engine){
|
||
|
|
this.engine=engine;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
组合关系:
|
||
|
|
|
||
|
|
```java
|
||
|
|
public class Heart{}
|
||
|
|
|
||
|
|
public class Person{
|
||
|
|
|
||
|
|
private Heart heart;
|
||
|
|
|
||
|
|
public Person(){
|
||
|
|
|
||
|
|
this.heart=new Heart();
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
关联关系:
|
||
|
|
|
||
|
|
该关系可分为单、双以及自关联等。
|
||
|
|
|
||
|
|
```java
|
||
|
|
public class Car{}
|
||
|
|
public class Person{
|
||
|
|
private Car car;
|
||
|
|
publicvoid setCar(Car car){
|
||
|
|
this.car=car;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
泛化关系:就是继承关系。
|
||
|
|
|
||
|
|
接口实现关系:继承接口。
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
模式2
|
||
|
|
|
||
|
|
工厂模式:
|
||
|
|
|
||
|
|
主要作用:用来制造对象。
|
||
|
|
|
||
|
|
工厂方法模式
|
||
|
|
|
||
|
|
主要作用:创建对象接口给子类实例化。
|
||
|
|
|
||
|
|
抽象工厂模式:
|
||
|
|
|
||
|
|
主要作用是用来为产品族而产生的模式。用来批量生产某个系列的操作的抽象模式。
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
模式3
|
||
|
|
|
||
|
|
单例模式:
|
||
|
|
|
||
|
|
作用:为了约束程序的实例化好的对象的唯一性,而产生的模式。防止一个实例出现重复的状态。
|
||
|
|
|
||
|
|
【注释:当程序采用了多线程的方法时,单例模式则失效,因为一个线程里面相当于一个程序,如果一个程序出现了副本的状态,这样的结果会导致两个线程会因为获取CPU的使用权限而出现混乱的现象。为解决这种混乱,我们则要对其进行加锁,使得程序能够一个实例(状态)运行。】
|
||
|
|
|
||
|
|
原型模式:
|
||
|
|
|
||
|
|
作用:定义一个对象,通过接口的方式将这个对象进行复制一份,用来定制化。形成一个新的对象来使用。
|
||
|
|
|
||
|
|
【这里衍生出一个浅复制和一个深复制的两个新概念,浅复制是指复制对象的数组、容器对象等。对于所引用的对象则不复制。相反则是深复制。】
|
||
|
|
|
||
|
|
建造者模式:
|
||
|
|
|