设计模式总结 (java版 1)
1. 简单工厂模式
需求: 设计一个计算器, 有一个抽象的运算类,他里边有两个数字属性和一个getResult()抽象方法,这个类被四个加减乘除的具体的算法类继承,然后有一个简单工厂类,这个简称工厂类是用来生成一个具体的运算类的,然后就在简单工厂类里有一个逻辑的判断,这个逻辑的判断会让简单工厂生成对应的具体类, 然后调用这个具体的类的getResult()方法就可以了.
抽象一个运算类
@Data
public abstract class Operation {
public Double numberA;
public Double numberB;
public abstract Double getResult();
}
有一个加法和减法的类来继承这个运算类
public class SubOperation extends Operation {
@Override
public Double getResult() {
Double result = 0.0;
result = numberA - numberB;
return result;
}
}
public class AddOperation extends Operation {
@Override
public Double getResult() {
Double result = 0.0;
result = numberA + numberB;
return result;
}
}
简单工厂用来判断产生哪种具体类型的运算类
public class SimpleFactory {
public static Operation createOperation(String type) {
Operation operation = null;
if ("add".equals(type)) {
operation = new AddOperation();
}
if ("sub".equals(type)) {
operation = new SubOperation();
}
return operation;
}
}
主函数 通过给简单工厂传入type来产生具体的运算类,并调用getResult方法获取结果
public class Client {
public static void main(String[] args) {
Operation operation = SimpleFactory.createOperation("add");
operation.numberB = 10.0;
operation.numberA = 5.0;
Double result = operation.getResult();
System.out.println(result);
}
}
需要注意这里的细节: 作为客户端的调用, 这里不仅要知道简单工厂这个类, 而且还需要调用operation的一个方法, 所以调用需要了解两个类;
2. 策略模式
如果一个商场需要一个收银软件,有不同的折扣方式, 比如满减, 比如打折; 这是不同的策略;也就相当于简单工厂模式里不同的operation,但是, 简单工厂模式在于调用者需要知道工厂类, 页需要知道具体的Operation类的getResult()方法, 所以, 策略模式下, 可以把上述的例子改成这样:
工厂类新增一个Operation对象, 并新增一个getResult()类, 用来调用Operation的getResult()方法
public class SimpleFactory {
public Operation operation;
public createOperation(String type) {
Operation operation = null;
if ("add".equals(type)) {
this.operation = new AddOperation();
}
if ("sub".equals(type)) {
this.operation = new SubOperation();
}
}
public double getResult() {
return operation.getResult();
}
}
public class Client {
public static void main(String[] args) {
Double result = SimpleFactory.createOperation("add").getResult();
System.out.println(result);
}
}
(getResult()方法需要调整一下, 但主要思想就是, 在简单工厂中去集成调用Operation的getResult()方法。
3. 装饰模式
装饰模式是这样的,当一个人需要有很多的衣服去穿搭,然后我们要在命令行中展示出这个人的姓名,然后他所穿的各种衣服
这个时候我们可以设计一个person类:
- 有一个show用来展示名字
然后有一个抽象的服饰类:
-
有一个field是人,
-
有一个装饰方法用来初始化自己的field,
-
有一个show方法, 如果filed不为空, 调用filed的show方法;
然后有一堆各种各样的服饰去继承这个抽象的服饰类,
- 每一个服饰类都要重写show方法, 受方法中,首先自定义自己要打印的东西, 然后去调用base.show(), 既自己的field的show方法;
Person:
@Data
public class Person {
private String name;
public void show() {
System.out.println("装扮的人: " + name);
}
}
Finery: 服饰类
public class Finery extends Person {
private Person person;
public void decorate(Person person) {
this.person = person;//重点
}
@Override
public void show() {
if (person != null) {
person.show();
}
}
}
具体的各种类:
public class TShirt extends Finery {
@Override
public void show() {
System.out.println("T恤");
super.show();//重点
}
}
主方法的调用:
Person xiaoCai = new Person("小菜");
TShirt tShirt = new TShirt();
Hat hat = new Hat();
tShirt.decorate(xiaoCai);
hat.decorate(tShirt);
hat.show();
装饰模式主要是可以动态的去添加装饰模式,主要是可以动态的去添加各种装饰,
也就是说, 在建造的过程中是不稳定的, 这是和建造者的主要区别。
4. 代理模式
别人代理你做事情
(例子: 帮别人送东西)
抽象的subject:
public abstract class Subject {
public abstract void request();
}
真实的subject
public class RealSubject extends Subject {
@Override
public void request() {
System.out.println("真实主题类的执行方法");
}
}
代理类:
public class Proxy extends Subject {
private RealSubject realSubject;
@Override
public void request() {
if (this.realSubject == null) {
this.realSubject = new RealSubject();
}
this.realSubject.request();
}
}
主函数:
public class Client {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request();
}
}
5. 工厂方法模式
每一个operation都又对应的工厂来产生
因为简单工厂模式其实违背了开放封闭原则,在需要新加一个运算类的时候, 需要修改简单工厂的方法,用来判断去生成哪种运算类, 而工厂方法模式 则遵循了开放封闭原则, 在需要添加一个新的运算类的时候,需要添加一个新的运算工厂类, 然后再添加一个新的运算类就可以了。
6. 原型模式
用原型实例指定创建对象的种类, 并通过拷贝这些原型创建新的对象;
简单来说就是通过克隆一个对象来创建另一个对象, 不过在java中涉及到深拷贝和浅拷贝到问题
7. 模版方法模式
模板方法模式主要是用来定义怎样把一堆方法用模板的方式来处理的模式, 也就是说,抽象类中有两个抽象方法,然后还有一个方法是用模板的方式来调用这两个抽象方法的, 而这两个抽象方法则由具体的类分别去实现不同的细节, 但是这个模板方法给出了逻辑的骨架,然后去调用这两个抽象方法的操作来实现细节的方法。
上图中的抽象内装有一个模板方法,这个模板方法中会调用抽象的操作, 而具体的那去实现这两个抽象的方法。
8. 外观模式
非常无聊, 类似买基金, 基金其实是多只股票的买入买出, 只暴露一个调用出来。
9. 建造者模式(生成器模式)
将一个复杂对象的构建, 和他的表示分离, 是的同样的构建过程可以创建不同的表示
以建造一个小人为例, 我要创建一个高的人,我要创建一个矮的人, 我需要让创建人这个过程是稳定的,不能缺胳膊少腿。
所以我要做的是抽象一个PersonBuilder, 里面有一个画笔属性, 然后有创建头, 手, 腿, 脚的各种抽象方法,
然后有 俩个具体的创建高或者矮的人的类, 分别去实现各种创建头手脚腿的抽象方法。
这个时候我们需要一个指挥者, 指挥者有一个PersonBuilder的属性, 同时有一个方法 来按照顺序固定的创建头手腿脚, 这样我们创建的人就不会有缺胳膊少腿的情况了, 保证了建造的稳定。
PersonBuilder:
@Data
public abstract class PersonBuilder {
private String pen;
public abstract void BuildHead();
public abstract void BuildBody();
public abstract void BuildArm();
public abstract void BuilderLeg();
}
TallPersonBuilder
public class TallPersonBuilder extends PersonBuilder {
@Override
public void BuildHead() {
System.out.println("具体的建造一个高一点人的头");
}
@Override
public void BuildBody() {
System.out.println("具体的建造一个高一点人的身体");
}
@Override
public void BuildArm() {}
@Override
public void BuilderLeg() {}
}
personDirector
public class PersonDirector {
private PersonBuilder personBuilder;
public PersonDirector(PersonBuilder personBuilder) {
this.personBuilder = personBuilder;
}
public void CreatePerson() {
personBuilder.BuildHead();
personBuilder.BuildBody();
personBuilder.BuildArm();
personBuilder.BuilderLeg();
}
}
Client:
public class Client {
public static void main(String[] args) {
PersonBuilder personBuilder = new TallPersonBuilder();
PersonDirector personDirector = new PersonDirector(personBuilder);
personDirector.CreatePerson();
}
}
如果是具体的产品的话, 可以在建造者中添加一个抽象方法来返回该产品。
10. 观察者模式
subject用来通知, observer用来观察
总的来说就是subject中 有一个observer的list, 在subject中有一个方法用来通知这个list中的每一个, 调用每一个observer的update方法来通知observer要去做什么
observer中也要有一个属性subject, 在update的方法中需要用到subject的状态
问题是在subject中有observer这个field, 在observer中也有subject这个field,更大的问题是,不同的observer中的update方法名必须是相同的, 双重的耦合;
解决方法: 事件委托
委托就是一种引用方法的类型(其实就是封装一下要update的方法, 给这个update方法规定一个确定的参数和返回值)具体的使用方式可以查看[ Spring事件发布与监听 ] - Roy2048 - 博客园
11. 抽象工厂模式
抽象工厂模式:
举个例子, 数据库中有两张表, User和Department, 但是要实现用不同的数据库的连接来对这两张表进行增加和查询的操作, 就相当于, 有两种抽象产品, 然后要去生产这两种产品, 但是会用到不同的工厂。 也就是一个抽象工厂是可以生产两种产品的, 但这两种产品又属于不同的类型。
既, 如果只有一张表User, 则其实是工厂方法模式, 而有多张表的时候,就变成了抽象工厂模式。
缺点: 如果要增加一张表, 则在sqlServerFactory, AccessFactory, IFactory都要添加相应的方法, 并添加一个新的具体表接口。
改进方法:
1 简单工厂模式
先使用简单工厂去实现, 既, 在一个简单工厂DataAccess中有两个方法, 用字符串判断哪个数据库, 然后生成相关的数据库操作类,
2 用反射来替换switch判断
代码中, 用Assembly.Load().CreateInstance("具体数据库类")来生成, 然后把这个字符串抽取成变量, 但是依然需要在代码中来指定变量的。
3 用反射+配置文件来实现
读取配置, 然后在代码中切换。
12. 状态模式
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,那就没必要用‘状态模式’了。
本来是在一个主函数中去switch判断, 下一步应该怎么办;而状态模式是在每一个具体的状态类中去判断下一步应该做什么。 相当于把主函数中的switch分散到每个状态中。
13. 适配器模式
target接口是客户所期待或者一直在使用的接口
现在要使用adaptee的方法, 需要adapter继承target, 并有一个私有属性adaptee, 在继承的target的方法中调用adaptee的方法,
对外表现为, 依然使用target对象, 但使用到了adaptee的方法。这用模式通常不在设计一个新系统时使用,而在对接或者维护的时候使用。
Target:
public class Target {
public void request() {
System.out.println("Target: The default target's behavior.");
}
}
Adaptee:
public class Adaptee {
public void specificRequest() {
System.out.println("Adaptee: I can work just fine!");
}
}
Adapter:
@Data
public class Adapter extends Target {
private Adaptee adaptee;
@Override
public void request() {
adaptee.specificRequest();
}
}
client:
public class Client {
public static void main(String[] args) {
Target target = new Adapter();
target.request();//client依然使用target的方法
}
}
14. 备忘录模式(没用)
15. 组合模式
组合模式将个体和整体以树的形式结合起来, 比如要创建一个树, 可以创建一个抽象的节点, 这个节点可以被叶节点(无法再添加节点), 和枝节点, 可以继续添加, 也就是所有的节点都继承抽象节点, 在枝节点中可以添加一个list用于存储其他的枝节点或者叶节点。具体可以看python版本的例子。设计模式
16. 迭代器模式
继承基本的迭代接口就可以了(循环遍历)
17. 单例模式
单例模式(Singleton),保证一个类仅有一个实例,并提供个访问它的全局访问点。
public class Singleton {
private static volatile Singleton singleton;//volatile 防止指令重排序, 保证有序性和可见性
private Singleton(){}
public Singleton getInstance() {//双重检查加锁
if (singleton == null) {
synchronized (Singleton.class) {//对Singleton.class这个类的内存地址锁定进行同步
//即使Singleton没有被实例化, 这个.class类对象也可以被锁定
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
18. 桥接模式
这种方式下, 如果新增一个手机品牌或者新增一个软件, 都需要很大的改动(比如修改抽象类, 增加手机品牌, 在之前的品牌下增加软件等, 需要修改很多东西)
所以修改构架为:
然后手机和软件需要联系起来:
先定义一个抽象的MobileSoft类, 然后写MobileGameSoft和MobileMusicSoft的具体类:
public abstract class MobileSoft {
public abstract void run();
}
MobileGameSoft
public class MobileGameSoft extends MobileSoft {
@Override
public void run() {
System.out.println("手机游戏软件运行");
}
}
MobileMusicSoft
public class MobileMusicSoft extends MobileSoft {
@Override
public void run() {
System.out.println("手机音乐软件运行");
}
}
然后定义手机品牌抽象类, 并有两个具体的品牌来继承:
public abstract class MobileBrand {
public MobileSoft mobileSoft;
public void setMobileSoft(MobileSoft mobileSoft) {
this.mobileSoft = mobileSoft;
}
public abstract void run();
}
MobileBrandN:
public class MobileBrandN extends MobileBrand {
@Override
public void run() {
System.out.println("手机品牌N运行");
mobileSoft.run();
}
}
MobileBrandM:
public class MobileBrandM extends MobileBrand {
@Override
public void run() {
mobileSoft.run();
}
}
在客户端的调用:
public class Client {
public static void main(String[] args) {
//要在品牌N里使用音乐软件:
MobileBrandN brandN = new MobileBrandN();
brandN.setMobileSoft(new MobileGameSoft());
brandN.run();
}
}
这样, 就是桥接, 如果新加手机品牌或者软件, 就很方便了。
标签:大话,笔记,public,class,抽象,模式,设计模式,方法,void From: https://www.cnblogs.com/Roy2048/p/18237582