目录
1.创建型模式(Creational patterns)
工厂方法模式: 当client不知道要创建哪个具体类的实例,或者不想在client代码中指明要具体创建的实例时,用工厂方法。定义一个用于创建对象的接口,让其子类来决定实例化哪一个类,从而使一个类的实例化延迟到其子类。
1. // 工厂模式
2. // 先建立工厂总接口,定义生产物品总接口的抽象方法
3. // 再实现子类工厂实例类,重写生产具体物品的方法
4.
5. public class FactoryPattern{
6. public static void main(String[] args){
7. new AppleFactory().makeObject().method();
new GrapeFactory().makeObject().method();
8. }
9. }
10.
11. // 工厂总接口
12. interface Factory{
13. Fruit makeObject();
14. }
15.
16. // 苹果工厂子类接口
17. class AppleFactory implements Factory{
18. @Override
19. public Apple makeObject(){
20. return new Apple();
21. }
22. }
23.
24. // 葡萄工厂子类接口
25. class GrapeFactory implements Factory{
26. @Override
27. public Grape makeObject(){
28. return new Grape();
29. }
30. }
31.
32. // 水果总接口
33. interface Fruit{
34. void method();
35. }
36.
37. // 苹果子类
38. class Apple implements Fruit{
39. @Override
40. public void method(){
41. System.out.println("苹果");
42. }
43. }
44.
45. // 葡萄子类
46. class Grape implements Fruit{
47. public void method(){
48. System.out.println("葡萄");
49. }
50. }
2.结构型模式(Structural patterns)
(1) 适配器模式(adapter)
当内部实现和客户端要求不匹配时,将某个类/接口转换为client期望的其他形式, 通过增加一个接口,将已存在的子类封装起来,client面向接口编程,从而隐藏了具体子类。
用电器来打个比喻:有一个电器的插头是三脚的,而现有的插座是两孔的,要使插头插上插座,我们需要一个插头转换器,这个转换器即是适配器。
具体解决方法:
// 适配器模式
// 问题: 客户端要展示一个向量,需要起点的坐标和长度
// 但是现在只提供了两点的坐标,且不能改动客户端的代码(display的参数)
// *** 可以提供一个接口适配器Shape
public class AdapterPattern{
public static void main(String[] args){
display(1, 2, 23, 1);
}
public static void display(double x1, double y1, double angle, double len){
Vector vector = VectorDisplay.make(x1, y1, angle, len);
vector.display(x1, y1, angle, len);
}
}
class Vector implements VectorDisplay{
double x1, y1;
double x2, y2;
public Vector(double x1, double y1, double x2, double y2){
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
}
public void display(double x1, double y1, double x2, double y2){
System.out.println("这就实现了鸭");
}
// 重写display2方法
@Override
public void display2(double x1, double y1, double angle, double len){
// 调用了转接口
display(x1, y1, y1 + len * Math.cos(angle), x1 + len * Math.sin(angle));
}
}
interface VectorDisplay{
// 静态工厂
static Vector make(double x1, double y1, double angle, double len){
return new Vector(x1, y1,y1 + len * Math.cos(angle), x1 + len * Math.sin(angle));
}
// 转化器,满足客户端的display2方法
void display2(double x1, double y1, double angle, double len);
}
(2) 装饰器模式(Decorator)
装饰器模式,顾名思义,就是在类上添加装饰,允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
// 装饰器模式,特点是构造方法参数是接口,继承接口又委托接口,构造时把参数接口赋值给自己接口(好绕口啊)
// 参数接口相当于基础功能,然后在下面添加新的功能
public class DecoratorPattern{
public static void main(String[] args){
Stack s1 = new ArrayStack();
Stack s2 = new ClearStack(new LockStack(s1));
}
}
// 总接口,有子类公用方法push, pop, size
interface Stack{
List<Integer> list = new ArrayList<>();
default void push(int data){
list.add(data);
}
default int pop(){
if(list.isEmpty())
System.exit(0);
int data = list.get(list.size() - 1);
list.remove(list.size() - 1);
return data;
}
default int size(){
return list.size();
}
}
// 普通线性栈
class ArrayStack implements Stack{}
// 装饰类,重要作用:可装饰性(构造方法的接口就是装饰)
abstract class StackDecorator implements Stack{
// 子类可以访问父类这个委托的接口,所以用protect
protected final Stack stack;
// 构造方法:传入基础接口
public StackDecorator(Stack stack){
this.stack = stack;
}
}
// 可锁栈,在实现接口的基础上装饰了一些其他功能
class LockStack extends StackDecorator{
// 所有的装饰类都要继承抽象类StackDecorator
private boolean lock = true;
public LockStack(Stack stack){
super(stack);
}
// 以下是这个类需要新增加的功能
@Override
public void push(int data){
if(! lock)
super.push(data);
else
System.out.println("已上锁,不能操作");
}
@Override
public int pop(){
if(! lock)
return super.pop();
else{
System.out.println("已上锁,不能操作");
return list.get(size() - 1);
}
}
public void unlock(){
lock = true;
}
public void lock(){
lock = true;
}
}
// 可清空栈
class ClearStack extends StackPattern{
public ClearStack(Stack stack){
super(stack);
}
public void clear(){
while(! list.isEmpty())
list.remove(0);
}
}
3.行为类模式(Behavioral patterns)
(1) 策略模式(Strategy)
有多种不同的算法来实现同一个任务,但需要client根据需要 动态切换算法,而不是写死在代码里, 为不同的实现算 法构造抽象接口,利用delegation,运行时动态传入client倾向的算法类实例。
/* 策略模式
实现一个策略总接口
用不同的策略子类实现它,重写方法
使用某种策略时的参数是接口,传入多态对象(多态)
*/
public class StrategyPattern{
public static void main(String[] args){
Strategy strategy = new Method1();
Solute solute = new Solute();
solute.solute(strategy);
}
}
// 策略总接口
interface Strategy{
void method();
}
// 策略方法1
class Method1 implements Strategy{
@Override
public void method(){
System.out.println("方法1");
}
}
// 策略方法2
class Method2 implements Strategy{
@Override
public void method(){
System.out.println("方法2");
}
}
// 解决问题的实例类
// 只管解决问题,以何种方式解决,取决于使用的多态类
class Solute{
public void solute(Strategy strategy){
strategy.method();
}
}
(2) 模板模式(Template)
用重写而不是委托实现共性操作,通常是同性的操作多,不同性的操作少。一个抽象类公开定义了执行它的方法的方式/模板,它的子类可以按需要重写方法实现,共性的步骤在抽象类内公共实现,差异化的步骤在各个子类中实现,但调用将以抽象类中定义的方式进行。
// 模板模式
// 按照模板往下写,一个模板可以被多个类继承,只能继承不能委托
public class TemplatePattern{
public static void main(String[] args){
Doing study = new Study();
study.doing();
Doing play = new Play();
play.doing();
}
}
// 总抽象类
abstract class Doing{
final void doing(){
start();
process();
end();
}
abstract void start();
abstract void process();
abstract void end();
}
// 实现抽象类的一个实例类
class Play extends Doing{
@Override
void start(){
System.out.println("开始玩");
}
@Override
void process(){
System.out.println("正在玩");
}
@Override
void end(){
System.out.println("还玩?不玩了");
}
}
// 实现抽象类的另一个实例类
class Study extends Doing{
@Override
void start(){
System.out.println("开始学习");
}
@Override
void process(){
System.out.println("正在学习");
}
@Override
void end(){
System.out.println("学个屁,不学了");
}
}
(3) 迭代器模式(Iterator)
迭代器模式是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
// 迭代器模式
public class IteratorPattern{
public static void main(String[] args){
MyList list = new MyList();
MyIterator iterator = list.getIterator();
while(iterator.hasNext())
System.out.println(iterator.next());
}
}
// 迭代器接口
interface MyIterator{
boolean hasNext();
String next();
}
// 容器接口
interface Contain{
MyIterator getIterator();
}
// 数组接口
class MyList implements Contain{
String[] arr = new String[]{"1", "4", "3", "2"};
// 获取迭代器
@Override
public MyIterator getIterator(){
// 返回内部数组
return new InnerList();
}
// 用一个内部数组类实现迭代器接口,重写
class InnerList implements MyIterator{
private int index = 0;
@Override
public boolean hasNext(){
return index < arr.length;
}
@Override
public String next(){
index ++;
return arr[index - 1];
}
}
}
(4) 访问者模式(Visitor)
使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
// Visitor模式
public class VisitorModel{
public static void main(String[] args){
Visitor visitorA = new VisitA(); // 访问者A
Visitor visitorB = new VisitB(); // 访问者B
// 被访问者只需要一个就行了,因为不同的是访问者,他们决定访问策略
VisitObject visitObject = new VisitObject(1, 2); // 被访问者
visitObject.accept(visitorA);
visitObject.accept(visitorB);
}
}
// 被访问的类
class VisitObject{
int a;
int b;
public VisitObject(int a, int b){
this.a = a;
this.b = b;
}
// 被访问者要提供接受访问者的方法,参数为访问者接口
// 传进来的对象自然是多态
public void accept(Visitor visitor){
visitor.visit(this);
}
}
// 访问者接口
interface Visitor{
// 访问者访问被访问者
public void visit(VisitObject a);
}
// 被访问者实现类,说明具体要访问那个对象
class VisitA implements Visitor{
@Override
public void visit(VisitObject visitObject){
System.out.println(visitObject.a);
}
}
class VisitB implements Visitor{
@Override
public void visit(VisitObject visitObject){
System.out.println(visitObject.b);
}
}
有问题欢迎大家指出~