设计模式

Posted by 梁小生 on 2019-02-01

常用设计模式的学习

单例模式(Singleton)

定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。比如说系统的任务管理器。

单例模式

  • 单利模式的关键点

1.构造函数不对外开放,一般为private

2.通过一个静态方法或者枚举返回单例类对象

3.确保单例类对象有且只有一个,尤其是在多线程环境下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton{

private volatile static Singleton singleton;

private Stingleton(){}

public static Singleton getInstance(){
synchronized(Singleton.class){
//判空则是为了在null情况下创建实例
if(singleton==null)
singleton=new Singleton();
}
return singleton;
}
}

静态工厂方法模式(Static Factory)

  • 将工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可
1
2
3
public interface Sender {  
public void Send();
}
1
2
3
4
5
6
public class MailSender implements Sender {  
@Override
public void Send() {
System.out.println("this is mailsender!");
}
}
1
2
3
4
5
6
7
public class SmsSender implements Sender {  

@Override
public void Send() {
System.out.println("this is sms sender!");
}
}
1
2
3
4
5
6
7
8
9
10
public class SendFactory {  

public static Sender produceMail(){
return new MailSender();
}

public static Sender produceSms(){
return new SmsSender();
}
}
1
2
3
4
5
6
7
// 测试类
public class FactoryTest {
public static void main(String[] args) {
Sender sender = SendFactory.produceMail();
sender.Send();
}
}

抽象工厂模式(Abstract Factory)

抽象工厂模式

  • 定义:抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。

  • 抽象工厂模式的好处就是,如果你现在想增加一个功能:发及时信息,则只需做一个实现类,实现Sender接口,同时做一个工厂类,实现Provider接口,就OK了,无需去改动现成的代码。这样做,拓展性较好!

1
2
3
4
// 动作接口
public interface Sender {
public void Send();
}
1
2
3
4
// 创建类的接口
public interface CreateProduce {
public Sender produce();
}
1
2
3
4
5
6
public class MailSender implements Sender {  
@Override
public void Send() {
System.out.println("this is mailsender!");
}
}
1
2
3
4
5
public class SmsSender implements Sender {  
@Override
public void Send() {
System.out.println("this is sms sender!");
}
1
2
3
4
5
6
public class SendSmsFactory implements CreateProduce{    
@Override
public Sender produce() {
return new SmsSender();
}
}
1
2
3
4
5
6
public class SendMailFactory implements CreateProduce{
@Override
public Sender produce() {
return new MailSender();
}
}
1
2
3
4
5
6
7
8
// 测试类
public class Test {
public static void main(String[] args) {
Provider provider = new SendMailFactory();
Sender sender = provider.produce();
sender.Send();
}
}

适配模式(Adapter)

定义:适配器模式将某个类的接口转换成客户端期望的另一个接口表示,目的是消除由于接口不匹配所造成的类的兼容性问题。主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。

适配模式

  • 类的适配器模式
1
2
3
4
5
public class Source {  
public void method1() {
System.out.println("this is original method!");
}
}
1
2
3
4
5
6
7
public interface Targetable {  
/* 与原类中的方法相同 */
public void method1();

/* 新类的方法 */
public void method2();
}
1
2
3
4
5
6
public class Adapter extends Source implements Targetable {  
@Override
public void method2() {
System.out.println("this is the targetable method!");
}
}
1
2
3
4
5
6
7
8
// target 可以使用他自己原来的method2方法和继承的method1方法
public class AdapterTest {
public static void main(String[] args) {
Targetable target = new Adapter();
target.method1();
target.method2();
}
}
  • 对象的适配器模式
1
2
3
4
5
public class Source {  
public void method1() {
System.out.println("this is original method!");
}
}
1
2
3
4
5
6
public interface Targetable {  

public void method1();

public void method2();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Wrapper implements Targetable {  

private Source source;

public Wrapper(Source source){
super();
this.source = source;
}

@Override
public void method1() {
source.method1();
}

@Override
public void method2() {
System.out.println("this is the targetable method!");
}
}
  • 接口的适配器模式
1
2
3
4
public interface Sourceable {   
public void method1();
public void method2();
}
1
2
3
4
5
public abstract class Wrapper2 implements Sourceable{  

public void method1(){}
public void method2(){}
}
1
2
3
4
5
public class SourceSub1 extends Wrapper2 {  
public void method1(){
System.out.println("the sourceable interface's first Sub1!");
}
}
1
2
3
4
5
public class SourceSub2 extends Wrapper2 {  
public void method2(){
System.out.println("the sourceable interface's second Sub2!");
}
}
1
2
3
4
5
6
7
8
9
10
11
public class WrapperTest {  
public static void main(String[] args) {
Sourceable source1 = new SourceSub1();
Sourceable source2 = new SourceSub2();

source1.method1();
source1.method2();
source2.method1();
source2.method2();
}
}

代理模式(Proxy)

定义:模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作。

1
2
3
public interface Sourceable {  
public void method();
}
1
2
3
4
5
6
public class Source implements Sourceable {  
@Override
public void method() {
System.out.println("the original method!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Proxy implements Sourceable {  

private Source source;
public Proxy(){
super();
this.source = new Source();
}
@Override
public void method() {
before();
source.method();
atfer();
}
private void atfer() {
System.out.println("after proxy!");
}
private void before() {
System.out.println("before proxy!");
}
}

外观模式(Facade)

定义:外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合度,该模式中没有涉及到接口,看下类图:(我们以一个计算机的启动过程为例)

外观模式

1
2
3
4
5
6
7
8
9
10
public class CPU {  

public void startup(){
System.out.println("cpu startup!");
}

public void shutdown(){
System.out.println("cpu shutdown!");
}
}
1
2
3
4
5
6
7
8
9
10
public class Memory {  

public void startup(){
System.out.println("memory startup!");
}

public void shutdown(){
System.out.println("memory shutdown!");
}
}
1
2
3
4
5
6
7
8
9
10
public class Disk {  

public void startup(){
System.out.println("disk startup!");
}

public void shutdown(){
System.out.println("disk shutdown!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Computer {  
private CPU cpu;
private Memory memory;
private Disk disk;

public Computer(){
cpu = new CPU();
memory = new Memory();
disk = new Disk();
}

public void startup(){
System.out.println("start the computer!");
cpu.startup();
memory.startup();
disk.startup();
System.out.println("start computer finished!");
}

public void shutdown(){
System.out.println("begin to close the computer!");
cpu.shutdown();
memory.shutdown();
disk.shutdown();
System.out.println("computer closed!");
}
}
1
2
3
4
5
6
7
8
public class User {  

public static void main(String[] args) {
Computer computer = new Computer();
computer.startup();
computer.shutdown();
}
}

桥接模式(Bridge)

定义:桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。桥接的用意是:将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。对接口编程,而不是对实现编程。

桥接模式

1
2
3
public interface Sourceable {  
public void method();
}
1
2
3
4
5
6
7
public class SourceSub1 implements Sourceable {  

@Override
public void method() {
System.out.println("this is the first sub!");
}
}
1
2
3
4
5
6
7
public class SourceSub2 implements Sourceable {  

@Override
public void method() {
System.out.println("this is the second sub!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class Bridge {  
private Sourceable source;

public void method(){
source.method();
}

public Sourceable getSource() {
return source;
}

public void setSource(Sourceable source) {
this.source = source;
}
}
1
2
3
4
5
public class MyBridge extends Bridge {
public void method(){
getSource().method();
}
}

组合模式(Composite)

定于:组合模式有时又叫部分-整体模式在处理类似树形结构的问题时比较方便,看看关系图:

组合模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class TreeNode {

private String name;
private TreeNode parent;
private Vector<TreeNode> children = new Vector<TreeNode>();

public TreeNode(String name){
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public TreeNode getParent() {
return parent;
}

public void setParent(TreeNode parent) {
this.parent = parent;
}

//添加孩子节点
public void add(TreeNode node){
children.add(node);
}

//删除孩子节点
public void remove(TreeNode node){
children.remove(node);
}

//取得孩子节点
public Enumeration<TreeNode> getChildren(){
return children.elements();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Tree {

TreeNode root = null;

public Tree(String name) {
root = new TreeNode(name);
}

public static void main(String[] args) {
Tree tree = new Tree("A");
TreeNode nodeB = new TreeNode("B");
TreeNode nodeC = new TreeNode("C");

nodeB.add(nodeC);
tree.root.add(nodeB);
System.out.println("build the tree finished!");
}
}

使用场景:将多个对象组合在一起进行操作,常用于表示树形结构中,例如二叉树,树等。

享元模式(Flyweight Pattern)

定义:享元模式(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能。这种类型的设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。

1
2
3
public interface Shape {
void draw();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;

public Circle(String color){
this.color = color;
}

public void setX(int x) {
this.x = x;
}

public void setY(int y) {
this.y = y;
}

public void setRadius(int radius) {
this.radius = radius;
}

@Override
public void draw() {
System.out.println("Circle: Draw() [Color : " + color
+", x : " + x +", y :" + y +", radius :" + radius);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.HashMap;

public class ShapeFactory {
private static final HashMap<String, Shape> circleMap = new HashMap<>();

public static Shape getCircle(String color) {
Circle circle = (Circle)circleMap.get(color);

if(circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color : " + color);
}
return circle;
}
}