자바 프로 그래 밍 사상 독서 노트-범 형(4)
50622 단어 자바
혼합 형:여러 가지 유형 을 혼합 하 는 능력 으로 혼합 형 중의 모든 유형 을 나 타 낼 수 있 는 유형 을 만 듭 니 다.
15.15.1 C++의 혼 형
15.15.2 인터페이스 와 혼합
인터페이스 사용 시 혼합 효과 발생:
package com.mzm.chapter15;
import java.util.Date;
/**
*
*/
public class Mixins {
public static void main(String[] args) {
Mixin mixin1 = new Mixin(), mixin2 = new Mixin();
mixin1.set("test string 1");
mixin2.set("test string 2");
System.out.println(mixin1.get() + " " + mixin1.getStamp() + " " + mixin1.getSerialNumber());
System.out.println(mixin2.get() + " " + mixin2.getStamp() + " " + mixin2.getSerialNumber());
}
}
interface TimeStamped {
long getStamp();
}
class TimeStampedImp implements TimeStamped {
private final long timeStamp;
public TimeStampedImp() {
timeStamp = new Date().getTime();
}
@Override
public long getStamp() {
return timeStamp;
}
}
interface SerialNumbered {
long getSerialNumber();
}
class SerialNumberImp implements SerialNumbered {
private static long counter = 1;
private final long serialNumber = counter++;
@Override
public long getSerialNumber() {
return serialNumber;
}
}
interface Basic {
void set(String val);
String get();
}
class BasicImp implements Basic {
private String value;
@Override
public void set(String val) {
value = val;
}
@Override
public String get() {
return value;
}
}
/**
* TimeStamped, SerialNumbered
* TimeStamped, SerialNumbered
*
*/
class Mixin extends BasicImp implements TimeStamped, SerialNumbered{
private TimeStamped timeStamped = new TimeStampedImp();
private SerialNumbered serialNumber = new SerialNumberImp();
@Override
public long getStamp() {
return timeStamped.getStamp();
}
@Override
public long getSerialNumber() {
return serialNumber.getSerialNumber();
}
}
본질은 프 록 시 모드 를 사용 하 는 것 입 니 다.모든 혼합 유형 은 목표 클래스 에 해당 하 는 구성원 변 수 를 대리 로 해 야 합 니 다.이런 방식 은 혼합 유형 이 비교적 많은 상황 에서 코드 량 이 급속히 증가 할 것 이다.
15.15.3 장식 기 모드 사용
장식 기 모드 는 레이 어 링 대상 을 사용 하여 하나의 대상 에 동적 으로 투명 하 게 책임 을 추가 합 니 다.장식 기 는 최초의 대상 주위 에 포 장 된 모든 대상 이 같은 기본 인 터 페 이 스 를 가지 고 있 음 을 지정 합 니 다.어떤 사물 은 장식 할 수 있 고 다른 종 류 를 장식 할 수 있 는 대상 의 주변 에 포장 함으로써 기능 을 층 으로 나 눌 수 있다.이 때문에 장식 기 에 대한 사용 은 투명 하 다.대상 이 장식 되 었 든 안 되 었 든 대상 에 게 보 낼 수 있 는 공공 메시지 집합 을 가지 고 있다.장식 류 에 도 새로운 방법 을 추가 할 수 있 지만 제한 을 받는다.장식 기 는 조합 과 형식화 구조(장식 가능 물/장식 기 차원 구조)를 사용 하여 이 루어 진 것 이 고 혼합 형 은 계승 을 바탕 으로 한다.따라서 매개 변수 화 유형 을 바탕 으로 하 는 혼합 형 을 일종 의 범 형 장식 기 체제 로 볼 수 있 고 이 체 제 는 장식 기 디자인 모델 의 계승 구 조 를 필요 로 하지 않 는 다.
package com.mzm.chapter15;
import java.util.Date;
/**
*
* , ,
* Created by on 2018/1/14.
*/
public class Decoration {
public static void main(String[] args) {
TimeStamped2 t = new TimeStamped2(new Basic2());
TimeStamped2 t2 = new TimeStamped2(new SerialNumbered2(new Basic2()));
//t2 TimeStamped2 , getSerialNumber()
//t2.getSerialNumber();
SerialNumbered2 s = new SerialNumbered2(new Basic2());
SerialNumbered2 s2 = new SerialNumbered2(new TimeStamped2(new Basic2()));
//s2 SerialNumbered2 , getStamp()
//s2.getStamp();
}
}
/**
*
*/
class Basic2 {
private String value;
public void set(String val) {
value = val;
}
public String get() {
return value;
}
}
/**
*
*/
class Decorator extends Basic2 {
protected Basic2 basic2;
public Decorator(Basic2 basic2) {
this.basic2 = basic2;
}
public void set(String val) {
basic2.set(val);
}
public String get() {
return basic2.get();
}
}
/**
*
*/
class TimeStamped2 extends Decorator {
private final long timeStamp;
public TimeStamped2(Basic2 basic2) {
super(basic2);
timeStamp = new Date().getTime();
}
public long getStamp() {
return timeStamp;
}
}
/**
*
*/
class SerialNumbered2 extends Decorator {
private static long counter = 1;
private final long serialNumber = counter++;
public SerialNumbered2(Basic2 basic2) {
super(basic2);
}
public long getSerialNumber() {
return serialNumber;
}
}
15.15.4 동적 에이전트 와 혼합
동적 에이 전 트 를 사용 하여 장식 기보 다 혼합 모델 에 더 가 까 운 메커니즘 을 만 들 수 있 습 니 다.동적 에이 전 트 를 사용 하면 클래스 의 동적 유형 은 이미 혼 입 된 조합 유형 이 될 것 입 니 다.
package com.mzm.chapter15;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;
/**
*
*/
public class DynamicProxyMixin {
public static void main(String[] args) {
Object mixin = MixinProxy.newInstance(
new TwoTuple(new BasicImp(), Basic.class),
new TwoTuple(new TimeStampedImp(), TimeStamped.class),
new TwoTuple(new SerialNumberImp(), SerialNumbered.class)
);
Basic b = (Basic) mixin;
TimeStamped t = (TimeStamped) mixin;
SerialNumbered s = (SerialNumbered) mixin;
b.set("Hello");
System.out.println(b.get());
System.out.println(t.getStamp());
System.out.println(s.getSerialNumber());
}
}
class MixinProxy implements InvocationHandler {
Map delegateByMethod;
@SuppressWarnings("unchecked")
public MixinProxy(TwoTuple
15.16 잠재 유형 메커니즘
잠재 적 유형 체제(구조 화 유형 체제/오리 유형 체제)는 이러한 유형 체 제 를 가 진 언어 는 특정한 유형 이나 인터페이스 가 아니 라 특정한 방법 부분 만 실현 하도록 요구한다.이러한 유형의 메커니즘 을 가 진 언어 는 전형 적 으로 Python 과 C++예 가 있다.Python:
class Dog(Object):
def speak(self):
print("Arf!")
def sit(self):
print("Sitting")
def reproduce(self):
pass
class Robot(Object):
def speak(self):
print("Click!")
def sit(self):
print("Clank!")
def oilChange(self):
pass
def perform(anything):
anything.speak()
anything.sit()
if __name__ == '__main__':
a = Dog()
b = Robot()
perform(a)
perform(b)
perform()함 수 는 잠재 적 인 인 터 페 이 스 를 포함 하고 있 지만 명시 적 으로 설명 할 필요 가 없습니다.분명히 대상 이 speak()와 sit()두 가지 방법 을 실현 하면 perform()함수 에 들 어 갈 수 있다.자바 는 잠재 적 인 형식 체 제 를 지원 하지 않 기 때문에 위의 코드 를 자바 버 전 으로 변환 하면 다음 과 같 습 니 다.
package com.mzm.chapter15;
/**
*
*/
public interface Performs {
void speak();
void sit();
}
package com.mzm.chapter15;
import com.mzm.chapter14.Dog;
/**
*
*/
public class DogsAndRobots {
public static void main(String[] args) {
PerformingDog d = new PerformingDog();
Robot r = new Robot();
Communicate.perform(d);
Communicate.perform(r);
}
}
class PerformingDog extends Dog implements Performs {
@Override
public void speak() {
System.out.println("Woof!");
}
@Override
public void sit() {
System.out.println("Sitting");
}
public void reproduce() {
}
}
class Robot implements Performs {
@Override
public void speak() {
System.out.println("Click!");
}
@Override
public void sit() {
System.out.println("Clank!");
}
public void oilChange() {
}
}
class Communicate {
public static void perform(T performer) {
performer.speak();
performer.sit();
}
}
15.17 잠재 적 유형 체제 에 대한 보상
15.17.1
반 사 를 통 해 자바 에서 잠재 적 인 유형 체 제 를 실현 할 수 있다.
package com.mzm.chapter15;
import java.lang.reflect.Method;
/**
*
*/
public class LatentReflection {
public static void main(String[] args) {
CommunicateReflectively.perform(new SmartDog());
CommunicateReflectively.perform(new Robot());
CommunicateReflectively.perform(new Mime());
}
}
class Mime {
public void walkAgainstTheWind() {
}
public void sit() {
System.out.println("Pretending to sit");
}
public void pushInvisibleWalls() {
}
public String toString() {
return "Mime";
}
}
class SmartDog {
public void speak() {
System.out.println("Woof!");
}
public void sit() {
System.out.println("Sitting");
}
public void reproduce() {
}
}
class CommunicateReflectively {
public static void perform(Object speaker) {
Class> spkr = speaker.getClass();
try {
try {
Method speak = spkr.getMethod("speak");
speak.invoke(speaker);
} catch (NoSuchMethodException e) {
System.out.println(speaker + " cannot speak");
}
try {
Method sit = spkr.getMethod("sit");
sit.invoke(speaker);
} catch (NoSuchMethodException e) {
System.out.println(speaker + " cannot sit");
}
} catch (Exception e) {
throw new RuntimeException(speaker.toString(), e);
}
}
}
15.17.2 한 방법 을 서열 에 적용 한다.
앞에서 반사 방식 을 이용 하여 잠재 적 인 유형 체 제 를 실현 하 였 으 나 모든 유형 검 사 를 운행 기간 으로 옮 겼 다.우 리 는 컴 파일 기간 유형 검사 와 잠재 적 유형 체 제 를 동시에 실현 할 수 있 기 를 바 랍 니 다.
package com.mzm.chapter15;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
public class Apply {
/**
*
* @param seq Iterable , T T
* @param f
* @param args
* @param
* @param
*/
public static extends Iterable extends T>> void apply(S seq, Method f, Object... args) {
try {
for(T t : seq) {
f.invoke(t, args);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class Shape {
public void rotate() {
System.out.println(this + " rotate");
}
public void resize(int newSize) {
System.out.println(this + " resize " + newSize);
}
}
class Square extends Shape {
}
class FilledList<T> extends ArrayList<T> {
public FilledList(Class extends T> type, int size) {
try {
for(int i = 0; i < size; i++) {
add(type.newInstance());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class ApplyTest {
public static void main(String[] args) throws Exception {
List shapes = new ArrayList<>();
for(int i = 0; i < 10; i++) {
shapes.add(new Shape());
}
Apply.apply(shapes, Shape.class.getMethod("rotate"));
Apply.apply(shapes, Shape.class.getMethod("resize", int.class), 5);
List squares = new ArrayList<>();
for(int i = 0; i < 10; i++) {
squares.add(new Square());
}
Apply.apply(squares, Shape.class.getMethod("rotate"));
Apply.apply(squares, Shape.class.getMethod("resize", int.class), 5);
Apply.apply(new FilledList<>(Shape.class, 10), Shape.class.getMethod("rotate"));
Apply.apply(new FilledList<>(Square.class, 10), Square.class.getMethod("rotate"));
SimpleQueue shapeQ = new SimpleQueue<>();
for(int i = 0; i < 5; i++) {
shapeQ.add(new Shape());
shapeQ.add(new Square());
}
Apply.apply(shapeQ, Shape.class.getMethod("rotate"));
}
}
15.17.3 당신 이 우연히 정확 한 인 터 페 이 스 를 가지 지 않 았 을 때
package com.mzm.chapter15;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
*
*/
public class Fill {
/**
*
* Collection
* Collection , SimpleQueue,
* @param collection , T
* @param classToken T Class
* @param size
* @param
*/
public static void fill(Collection collection, Class extends T> classToken, int size) {
for(int i = 0; i < size; i++) {
try {
collection.add(classToken.newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
class Contract {
private static long counter = 0;
private final long id = counter++;
public String toString() {
return getClass().getName() + " " + id;
}
}
class TitleTransfer extends Contract {
public static void main(String[] args) {
List contracts = new ArrayList<>();
Fill.fill(contracts, Contract.class, 3);
Fill.fill(contracts, TitleTransfer.class, 2);
for(Contract c : contracts) {
System.out.println(c);
}
SimpleQueue contractsQ = new SimpleQueue<>();
//SimpleQueue Collection
//Fill.fill(contractsQ, Contract.class, 3);
}
}
Fill 류 의 fill()방법 은 Collection 인 터 페 이 스 를 실현 한 용기 대상 에 만 적용 되 며,이 인 터 페 이 스 를 실현 하지 못 한 용기 대상 에 대해 서 는 add()방법 이 있어 도 fill()방법 을 사용 할 수 없습니다.이 방법 은 콜 렉 션 의 계승 범위 에 사용 범 위 를 한정 하기 때문에 그렇게 일반화 되 지 않 는 다.그리고 잠재 적 인 유형 체 제 를 사용 하 는 매개 변수 화 유형 체 제 를 사용 해 야 진정 으로 일반화 할 수 있다.
15.17.4 어댑터 로 잠재 적 유형 메커니즘 모방
잠재 적 인 형식 체 제 는 실제로 필요 한 방법 을 포함 하 는 암시 적 인 인 터 페 이 스 를 만 들 었 습 니 다.이 인 터 페 이 스 를 손 으로 만 들 면 문 제 를 해결 할 수 있 습 니 다.기 존의 인터페이스 에서 코드 를 작성 하여 필요 한 인 터 페 이 스 를 만 드 는 것 은 어댑터 디자인 모델 의 전형 적 인 예 이다.
package com.mzm.chapter15;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
*
*
*/
public class Fill2 {
/**
* Class fill()
* @param addable Addable , T
* @param classToken Class
* @param size
* @param
*/
public static void fill(Addable addable, Class extends T> classToken, int size) {
for(int i = 0; i < size; i++) {
try {
addable.add(classToken.newInstance());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
/**
* fill()
* @param addable Addable , T
* @param generator Class
* @param size
* @param
*/
public static void fill(Addable addable, Generator generator, int size) {
for(int i = 0; i < size; i++) {
addable.add(generator.next());
}
}
}
/**
* ,
* @param
*/
interface Addable {
void add(T t);
}
/**
* , Collection
* @param
*/
class AddableCollectionAdapter implements Addable {
private Collection c;
public AddableCollectionAdapter(Collection c) {
this.c = c;
}
@Override
public void add(T item) {
c.add(item);
}
}
/**
*
*/
class Adapter {
public static Addable collectionAdapter(Collection c) {
return new AddableCollectionAdapter<>(c);
}
}
/**
* SimpleQueue , Addable
* @param
*/
class AddableSimpleQueue extends SimpleQueue implements Addable {
public void add(T item) {
super.add(item);
}
}
class Fill2Test {
public static void main(String[] args) {
//Collection
List carrier = new ArrayList<>();
Fill2.fill(new AddableCollectionAdapter<>(carrier), Coffee.class, 3);
Fill2.fill(Adapter.collectionAdapter(carrier), Latte.class, 2);
for(Coffee c : carrier) {
System.out.println(c);
}
System.out.println("----------------------------------------------");
// AddableSimpleQueue
AddableSimpleQueue coffeeQ = new AddableSimpleQueue<>();
Fill2.fill(coffeeQ, Mocha.class, 4);
Fill2.fill(coffeeQ, Latte.class, 1);
for(Coffee c : coffeeQ) {
System.out.println(c);
}
}
}
하지만 어댑터 를 사용 하 는 것 은 추가 적 인 절차 다.
15.18 함수 대상 을 전략 으로 사용 합 니 다.
package com.mzm.chapter15;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
*
*
*/
public class Functional {
/**
* reduce
* @param seq
* @param combiner
* @param
* @return combiner
*/
public static T reduce(Iterable seq, Combiner combiner) {
Iterator it = seq.iterator();
if(it.hasNext()) {
T result = it.next();
while(it.hasNext()) {
result = combiner.combine(result, it.next());
}
return result;
}
return null;
}
/**
* foreach
* @param seq
* @param func
* @param
* @return
*/
public static Collector forEach(Iterable seq, Collector func) {
for(T t : seq) {
func.function(t);
}
return func;
}
/**
* transform
* @param seq
* @param func , T R
* @param
* @param
* @return T R
*/
public static List transform(Iterable seq, UnaryFunction func) {
List result = new ArrayList<>();
for(T t : seq) {
result.add(func.function(t));
}
return result;
}
/**
* filter
* @param seq
* @param pred , true false
* @param
* @return ,
*/
public static List filter(Iterable seq, UnaryPredicate pred) {
List result = new ArrayList<>();
for(T t : seq) {
if(pred.test(t)) {
result.add(t);
}
}
return result;
}
/**
*
*/
static class IntegerAdder implements Combiner {
@Override
public Integer combine(Integer x, Integer y) {
return x + y;
}
}
/**
*
*/
static class IntegerSubtracter implements Combiner {
@Override
public Integer combine(Integer x, Integer y) {
return x - y;
}
}
/**
*
*/
static class BigDecimalAdder implements Combiner {
@Override
public BigDecimal combine(BigDecimal x, BigDecimal y) {
return x.add(y);
}
}
/**
*
*/
static class BigIntegerAdder implements Combiner {
@Override
public BigInteger combine(BigInteger x, BigInteger y) {
return x.add(y);
}
}
/**
*
*/
static class AtomicLongAdder implements Combiner {
@Override
public AtomicLong combine(AtomicLong x, AtomicLong y) {
return new AtomicLong(x.addAndGet(y.get()));
}
}
/**
* (ulp)
*/
static class BigDecimalUlp implements UnaryFunction {
@Override
public BigDecimal function(BigDecimal x) {
return x.ulp();
}
}
/**
*
* @param Comparable
*/
static class GreaterThan> implements UnaryPredicate{
private T bound;
public GreaterThan(T bound) {
this.bound = bound;
}
@Override
public boolean test(T x) {
return x.compareTo(bound) > 0;
}
}
/**
* ,
*/
static class MultiplyingIntegerCollector implements Collector {
private Integer val = 1;
@Override
public Integer function(Integer x) {
val *= x;
return val;
}
@Override
public Integer result() {
return val;
}
}
public static void main(String[] args) {
List li = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
Integer result = reduce(li, new IntegerAdder());
System.out.println(result);
result = reduce(li, new IntegerSubtracter());
System.out.println(result);
System.out.println(filter(li, new GreaterThan<>(4)));
System.out.println(forEach(li, new MultiplyingIntegerCollector()).result());
System.out.println(forEach(filter(li, new GreaterThan<>(4)), new MultiplyingIntegerCollector()).result());
MathContext mc = new MathContext(7);
List lbd = Arrays.asList(
new BigDecimal(1.1, mc),
new BigDecimal(2.2, mc),
new BigDecimal(3.3, mc),
new BigDecimal(4.4, mc)
);
BigDecimal rbd = reduce(lbd, new BigDecimalAdder());
System.out.println(rbd);
System.out.println(filter(lbd, new GreaterThan<>(new BigDecimal(3))));
List lbi = new ArrayList<>();
BigInteger bi = BigInteger.valueOf(11);
for(int i = 0; i < 11; i++) {
lbi.add(bi);
bi = bi.nextProbablePrime();
}
System.out.println(lbi);
BigInteger rbi = reduce(lbi, new BigIntegerAdder());
System.out.println(rbi);
System.out.println(rbi.isProbablePrime(5));
List lal = Arrays.asList(
new AtomicLong(11),
new AtomicLong(47),
new AtomicLong(74),
new AtomicLong(133)
);
AtomicLong ral = reduce(lal, new AtomicLongAdder());
System.out.println(ral);
System.out.println(transform(lbd, new BigDecimalUlp()));
}
}
/**
* , ,
* @param
*/
interface Combiner {
T combine(T x, T y);
}
/**
* , ,
* @param
* @param
*/
interface UnaryFunction {
R function(T x);
}
/**
*
* @param
*/
interface Collector extends UnaryFunction {
T result();
}
/**
* , ,
* @param
*/
interface UnaryPredicate {
boolean test(T x);
}
여기 서 자바 를 사용 하여 함수 식 프로 그래 밍 을 실현 합 니 다.그 중에서 Combiner,Unary Function,Collector 와 Unary Predicate 는 다른 언어 에서 이른바 잠재 적 인 유형 체 제 를 사용 하여 실현 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.